RSA 加密解密

RSA 算法

RSA 是一種非對稱加密算法,很多表單的密碼都采用 RSA 加密。
使用 RSA 一般需要先產生一對公鑰和私鑰残揉,當采用公鑰加密時,使用私鑰解密闪湾;采用私鑰加密時脖祈,使用公鑰解密椿访。

編寫一個工具類

package com.stf.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * add by sn
 */
public class RSAUtils {

    // 用于封裝隨機產生的公鑰與私鑰
    private static Map<Integer, String> keyMap = new HashMap<>();
    /**
     * 隨機生成密鑰對
     * @throws NoSuchAlgorithmException
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator 類用于生成公鑰和私鑰對,基于 RSA 算法生成對象
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        // 初始化密鑰對生成器,密鑰大小為 96~1024 位
        keyPairGenerator.initialize(512, new SecureRandom());
        // 生成一個密鑰對砌创,保存在 keyPair 中
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 得到私鑰
        RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
        // 得到公鑰
        RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
        String  publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到私鑰字符串
        String privateKeyString = new String(Base64.encodeBase64(privateKey.getEncoded()));
        // 將公鑰和私鑰保存到 Map
        keyMap.put(0, publicKeyString); // 0 表示公鑰
        keyMap.put(1, privateKeyString); // 1 表示私鑰
    }

    /**
     * RSA 公鑰加密
     * @param str   加密字符串
     * @param publicKey 公鑰
     * @return  密文
     * @throws Exception    加密過程中的異常信息
     */
    public static String encrypt(String str, String publicKey) throws Exception {
        // base64 編碼的公鑰
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        // RSA 加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
    }

    /**
     * RSA 私鑰解密
     * @param str   加密字符串
     * @param privateKey    私鑰
     * @return  明文
     * @throws Exception    解密過程中的異常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception {
        // 64 位解碼加密后的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
        // base64 編碼的私鑰
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey)KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        // RSA 解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return new String(cipher.doFinal(inputByte));
    }
}

測試一下

public static void main(String[] args) throws Exception {
        // 生成公鑰和私鑰
        genKeyPair();
        // 加密字符串
        String message = "123456";
        System.out.println("隨機生成的公鑰為:" + keyMap.get(0));
        System.out.println("隨機生成的私鑰為:" + keyMap.get(1));
        String messageEn = encrypt(message, keyMap.get(0));
        System.out.println(message + "\t 加密后的字符串為:" + messageEn);
        System.out.println("\t 加密后的字符串長度為:" + messageEn.length());
        String messageDe = decrypt(messageEn, keyMap.get(1));
        System.out.println("還原后的字符串為:" + messageDe);
    }

執(zhí)行結果如下:

隨機生成的公鑰為:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJspBdgp9ACBvAFlqyUXQ7E0LqlizzDJ3zUEaK0ZyYITuIyq9UhYT1Sh/gQHntjRKiMekpfcFCDexVcNEAeItdUCAwEAAQ==
隨機生成的私鑰為:MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAmykF2Cn0AIG8AWWrJRdDsTQuqWLPMMnfNQRorRnJghO4jKr1SFhPVKH+BAee2NEqIx6Sl9wUIN7FVw0QB4i11QIDAQABAkAYCjEXnthpQ7CHXuM3afVY/UbFg8OqQXzN0BMPztED0B+l/3JyyJJ0Qw7yyWcfCWQf8j03DPrDFjAgKwW29O5BAiEA7lfNkH/M19Yfq1SFxTZmVlRMWsoVQJRmySwjdCXkGx0CIQCmp6bGGEn8Y7Ix3SGx48DSD0256g8wU4RB/sNXJ51QGQIhAKIXQIvW/l6DFsKUFu2KE4r+hXbxHAbxZf3GcM4avsjZAiAU1Yaq4yR0sf33794jgAZ9/D3KTTGC6B3zpibDgYdQGQIhAJ5+/PXDKxsDDWSrzlCyLSWdXMrGHCgtFGC87l6vhHR5
123456 加密后的字符串為:JubrLQlF7nJN98HCgVOUz6e5mN+A665eSBTahLhDIccjVwBSdjFGyAy4bbT7eVdEjzB3NPUmRuB8PH2e1KPhYw==
加密后的字符串長度為:88
還原后的字符串為:123456

應用

在實際應用中弛说,我們可以先執(zhí)行 genKeyPair 先生成一對密鑰句柠,將該對密鑰保存在配置文件中冀泻,然后在加密時,調用 encrypt(str, publicKey) 方法使用公鑰對文本進行加密裆站,在解密時条辟,調用 decrypt(strEn, privateKey) 方法使用私鑰對文本進行解密黔夭,即可。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末羽嫡,一起剝皮案震驚了整個濱河市本姥,隨后出現的幾起案子,更是在濱河造成了極大的恐慌杭棵,老刑警劉巖婚惫,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異魂爪,居然都是意外死亡先舷,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門滓侍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蒋川,“玉大人,你說我怎么就攤上這事撩笆∞嗲颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵浇衬,是天一觀的道長懒构。 經常有香客問我,道長耘擂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任絮姆,我火速辦了婚禮醉冤,結果婚禮上,老公的妹妹穿的比我還像新娘篙悯。我一直安慰自己蚁阳,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布鸽照。 她就那樣靜靜地躺著螺捐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矮燎。 梳的紋絲不亂的頭發(fā)上定血,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音诞外,去河邊找鬼澜沟。 笑死,一個胖子當著我的面吹牛峡谊,可吹牛的內容都是我干的茫虽。 我是一名探鬼主播刊苍,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼濒析!你這毒婦竟也來了正什?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤号杏,失蹤者是張志新(化名)和其女友劉穎埠忘,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體馒索,經...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡莹妒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了绰上。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旨怠。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蜈块,靈堂內的尸體忽然破棺而出鉴腻,到底是詐尸還是另有隱情,我是刑警寧澤百揭,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布爽哎,位于F島的核電站,受9級特大地震影響器一,放射性物質發(fā)生泄漏课锌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一祈秕、第九天 我趴在偏房一處隱蔽的房頂上張望渺贤。 院中可真熱鬧,春花似錦请毛、人聲如沸志鞍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽固棚。三九已至,卻和暖如春仙蚜,著一層夾襖步出監(jiān)牢的瞬間此洲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工鳍征, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留黍翎,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓艳丛,卻偏偏與公主長得像匣掸,于是被迫代替她去往敵國和親趟紊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內容

  • 16宿命:用概率思維提高你的勝算 以前的我是風險厭惡者碰酝,不喜歡去冒險霎匈,但是人生放棄了冒險,也就放棄了無數的可能送爸。 ...
    yichen大刀閱讀 6,050評論 0 4
  • 公元:2019年11月28日19時42分農歷:二零一九年 十一月 初三日 戌時干支:己亥乙亥己巳甲戌當月節(jié)氣:立冬...
    石放閱讀 6,879評論 0 2
  • 今天上午陪老媽看病铛嘱,下午健身房跑步,晚上想想今天還沒有斷舍離袭厂,馬上做墨吓,衣架和旁邊的的布衣架,一看亂亂纹磺,又想想自己是...
    影子3623253閱讀 2,912評論 1 8