JAVA中的RSA加密/解密/簽名/驗(yàn)簽操作

背景

在對(duì)接三方接口或?qū)崿F(xiàn)開放平臺(tái)操作時(shí)需要對(duì)接口提交參數(shù)通過RSA公鑰進(jìn)行加密,在獲取到請(qǐng)求數(shù)據(jù)后需要使用RSA私鑰對(duì)數(shù)據(jù)進(jìn)行解密操作。

RSA生成工具

支付寶的RSA生成工具

幾種方式

1.自定義RsaUtil工具類

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * RSA加解密工具
 *
 * @author sdevil507
 * created on 2021/5/27
 */
@Slf4j
public class RsaUtil {

    /**
     * 算法
     */
    private static final String KEY_ALGORITHM = "RSA";

    /**
     * 類型
     */
    public static final String RSA_TYPE = "RSA/ECB/PKCS1Padding";

    /**
     * 簽名算法
     */
    public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";

    /**
     * 獲取轉(zhuǎn)換后的公鑰
     *
     * @param publicKey 公鑰字符串
     * @return 轉(zhuǎn)換后的公鑰
     */
    private static PublicKey getPublicKey(String publicKey) {
        try {
            byte[] byteKey = Base64.decodeBase64(publicKey);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            return keyFactory.generatePublic(x509EncodedKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 獲取轉(zhuǎn)換后的私鑰
     *
     * @param privateKey 私鑰字符串
     * @return 轉(zhuǎn)換后的私鑰
     */
    private static PrivateKey getPrivateKey(String privateKey) {
        try {
            byte[] byteKey = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(byteKey);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 私鑰簽名
     *
     * @param privateKey 私鑰
     * @param plainText  明文
     * @return 簽名字符串
     */
    public static String sign(String privateKey, String plainText) {
        String signStr = null;
        byte[] signeBytes;
        try {
            log.info("簽名前明文:{}", plainText);
            PrivateKey key = getPrivateKey(privateKey);
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(key);
            signature.update(plainText.getBytes());
            signeBytes = signature.sign();
            signStr = Base64.encodeBase64String(signeBytes);
            log.info("簽名后密文:{}", signStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return signStr;
    }

    /**
     * 公鑰驗(yàn)簽
     *
     * @param plainText 待驗(yàn)簽明文
     * @param signStr   簽名密文
     * @return true/false
     */
    public static boolean verifySign(String publicKey, String plainText, String signStr) {
        boolean verifySignSuccess = false;
        try {
            PublicKey key = getPublicKey(publicKey);
            Signature verifySign = Signature.getInstance(SIGNATURE_ALGORITHM);
            verifySign.initVerify(key);
            verifySign.update(plainText.getBytes());
            verifySignSuccess = verifySign.verify(Base64.decodeBase64(signStr));
            log.info("公鑰驗(yàn)簽結(jié)果:{}", verifySignSuccess);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return verifySignSuccess;
    }

    /**
     * 明文加密
     *
     * @param publicKey 公鑰
     * @param plainText 明文
     * @return 密文
     */
    public static String encrypt(String publicKey, String plainText) {
        String encryptedBase64 = "";
        try {
            Key key = getPublicKey(publicKey);
            final Cipher cipher = Cipher.getInstance(RSA_TYPE);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // 轉(zhuǎn)換
            byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
            encryptedBase64 = Base64.encodeBase64String(encryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return encryptedBase64;
    }

    /**
     * 密文解密
     *
     * @param privateKey      秘鑰
     * @param encryptedBase64 密文
     * @return 明文
     */
    public static String decrypt(String privateKey, String encryptedBase64) {
        String decryptedString = "";
        try {
            Key key = getPrivateKey(privateKey);
            final Cipher cipher = Cipher.getInstance(RSA_TYPE);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] encryptedBytes = Base64.decodeBase64(encryptedBase64);
            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
            decryptedString = new String(decryptedBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptedString;
    }
}

2.使用hutool工具類中的RSA工具類

引入hutool類庫

<dependency>
    <groupId>com.xiaoleilu</groupId>
    <artifactId>hutool-all</artifactId>
    <version>x.x.x</version>
</dependency>

測試代碼

    @Test
    public void hutoolRsa() {
        // 公鑰
        String publicKey = "xxx";
        // 私鑰
        String privateKey = "xxx";
        // 明文內(nèi)容
        String content = "test123456helloWorld";
        // 使用公鑰,私鑰初始化RSA對(duì)象
        RSA rsa = new RSA(privateKey, publicKey);
        // 公鑰加密
        String encryptStr = rsa.encryptBase64(content, KeyType.PublicKey);
        System.out.println(encryptStr);
        // 私鑰解密
        String plainText = rsa.decryptStr(encryptStr, KeyType.PrivateKey);
        System.out.println(plainText);
    }

可以繼續(xù)封裝實(shí)現(xiàn)自己的簽名/驗(yàn)簽方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市傲须,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖谦疾,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異犬金,居然都是意外死亡念恍,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門晚顷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來峰伙,“玉大人,你說我怎么就攤上這事该默⊥ィ” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵栓袖,是天一觀的道長匣摘。 經(jīng)常有香客問我,道長裹刮,這世上最難降的妖魔是什么音榜? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮必指,結(jié)果婚禮上囊咏,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好梅割,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布霜第。 她就那樣靜靜地躺著,像睡著了一般户辞。 火紅的嫁衣襯著肌膚如雪泌类。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天底燎,我揣著相機(jī)與錄音刃榨,去河邊找鬼。 笑死双仍,一個(gè)胖子當(dāng)著我的面吹牛枢希,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播朱沃,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苞轿,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了逗物?” 一聲冷哼從身側(cè)響起搬卒,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翎卓,沒想到半個(gè)月后契邀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡失暴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年坯门,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锐帜。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡田盈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缴阎,到底是詐尸還是另有隱情,我是刑警寧澤简软,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布蛮拔,位于F島的核電站,受9級(jí)特大地震影響痹升,放射性物質(zhì)發(fā)生泄漏建炫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一疼蛾、第九天 我趴在偏房一處隱蔽的房頂上張望肛跌。 院中可真熱鬧,春花似錦、人聲如沸衍慎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稳捆。三九已至赠法,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乔夯,已是汗流浹背砖织。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留末荐,地道東北人侧纯。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像甲脏,于是被迫代替她去往敵國和親茂蚓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容