位置: IT常识 - 正文

前后端RSA互相加解密、加签验签、密钥对生成(Java)(rsa前端解密)

编辑:rootadmin
前后端RSA互相加解密、加签验签、密钥对生成(Java) 目录一、序言二、关于PKCS#1和PKCS#8格式密钥1、简介2、区别二、关于JSEncrypt三、关于jsrsasign四、前端RSA加解密、加验签示例1、相关依赖2、cryptoUtils工具类封装3、测试用例五、Java后端RSA加解密、加验签1、CryptoUtils工具类封装2、测试用例六、前后端加解密、加验签交互测试1、前端加密,后端解密(1) 前端代码(2) 后端代码2、后端加密,前端解密(1) 后端代码(2) 前端代码3、前端加签,后端验签(1) 前端代码(2) 后端代码4、后端加签,前端验签(1) 后端代码(2) 前端代码一、序言

推荐整理分享前后端RSA互相加解密、加签验签、密钥对生成(Java)(rsa前端解密),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:rsa前端加密,rsa详解,前端rsa加密安全吗,前后端rsa加密,rsa前端加密后端解密,rsa前端解密,rsa算法后门,rsa前端加密后端解密,内容如对您有帮助,希望把文章链接给更多的朋友!

最近有一些安全性要求比较高的场景,我们提供API给第三方商户用于收单,其中有几个功能是绑卡、ATM/POS密码变更。

出于合规和监管要求,第三方商户不能保存卡号、CVV、密码等敏感信息,所以相关的敏感操作必须在接口提供方H5页面中完成。为了最大程度保证安全性,我们决定对敏感信息进行加密传输,同时对请求参数进行加签处理。

由于前端并不需要解密操作,最终我们选择RSA非对称加密,前端这块主要采用jsencrypt进行加解密,jsrsasign用来生成密钥对、加签验签。

二、关于PKCS#1和PKCS#8格式密钥

由于Java非对称加解密、加验签都是采用PKCS#8格式的密钥,PKCS#1格式的密钥跑不通,这里先简单介绍一下两者的区别。

1、简介

PKCS#1和PKCS#8是两个不同的数字证书标准。

PKCS#1是一个公钥加密标准,它定义了使用RSA算法进行加密和签名的格式。主要用于对数字签名、加密以及数字签名验证等应用。

PKCS#8则是一个私钥保护标准,它定义了私钥的存储格式。它主要用于在文件中对私钥进行保护,以防止意外泄露或不当使用。

总的来说,PKCS#1是针对公钥的标准,而PKCS#8是针对私钥的标准。

2、区别

两者的密钥格式不一样,下面以标准.pem格式为例,看下PKCS#1格式和PKCS#8格式密钥的区别:

PKCS#1格式私钥:-----BEGIN RSA PRIVATE KEY-----MIICXAIBAAKBgQC5BW6T9GVaaG/epGDjPpY3wN0DrBt+NojvxkEgpUdOAxgAepqe...TbzKH/LEqZN8WVau3bf41yAx2YoaOsIJJtOUTYcfh14=-----END RSA PRIVATE KEY-----PKCS#8格式私钥:-----BEGIN PRIVATE KEY-----MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALkFbpP0ZVpob96k...wgkm05RNhx+HXg==-----END PRIVATE KEY-----PKCS#1格式公钥:-----BEGIN RSA PUBLIC KEY-----MIICXAIBAAKBgQC5BW6T9GVaaG/epGDjPpY3wN0DrBt+NojvxkEgpUdOAxgAepqe...TbzKH/LEqZN8WVau3bf41yAx2YoaOsIJJtOUTYcfh14=-----END RSA PUBLIC KEY-----PKCS#8格式公钥:-----BEGIN PUBLIC KEY-----MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALkFbpP0ZVpob96k...wgkm05RNhx+HXg==-----END PUBLIC KEY-----

二、关于JSEncrypt

JSEncrypt是前端RSA加解密、密钥生成的一个实现方案,API也比较简单,更多请参考:JSEncrypt官网。

官网有个线上的Demo,可以生成非对称密钥,还有加解密。

Home页有相关的使用示例,还是很简单的。

// Create the encryption object and set the key.var crypt = new JSEncrypt();crypt.setKey(__YOUR_OPENSSL_PRIVATE_OR_PUBLIC_KEY__); //You can use also setPrivateKey and setPublicKey, they are both alias to setKey//Eventhough the methods are called setPublicKey and setPrivateKey, remember//that they are only alias to setKey, so you can pass them both a private or//a public openssl key, just remember that setting a public key allows you to only encrypt.var text = 'test';// Encrypt the data with the public key.var enc = crypt.encrypt(text);// Now decrypt the crypted text with the private key.var dec = crypt.decrypt(enc);// Now a simple check to see if the round-trip worked.if (dec === text){ alert('It works!!!');} else { alert('Something went wrong....');}

备注:Download页有JSEncrypt官网demo的源代码。

三、关于jsrsasign

jsrsasign是一个开源的纯JavaScript加密库,支持RSA/RSAPSS/ECDSA/DSA签名和验签,PKCS#1/5/8公私钥生成等等。

在Github上有两篇文章,一篇是关于如何使用Signature类进行加签、验签的,一篇是关于jsrsasign和Java互用性的,里面有通过Java加签,通过jsrsasign验签的demo。

前后端RSA互相加解密、加签验签、密钥对生成(Java)(rsa前端解密)

更多相关类和方法的使用和描述可以参考,jsrsasign API文档说明。

四、前端RSA加解密、加验签示例1、相关依赖// JSEncryptnpm i jsencrypt// jsrsasignnpm i jsrsasign2、cryptoUtils工具类封装import CryptoJS from "crypto-js";import JSEncrypt from "jsencrypt";import JsRsaSign from "jsrsasign";/** * RSA加密 * @param publicKey 公钥 * @param plainText 明文 * @returns {*} 密文 */export function encryptByRSA(publicKey, plainText) { const encryptor = new JSEncrypt(); encryptor.setPublicKey(publicKey); return encryptor.encrypt(plainText);}/** * RSA解密 * @param privateKey 私钥 * @param cipherText 密文 * @returns {*} 明文 */export function decryptByRSA(privateKey, cipherText) { const decrypter = new JSEncrypt(); decrypter.setPrivateKey(privateKey); return decrypter.decrypt(cipherText);}/** * 生成RSA密钥对,填充模式为PKCS8。 * 更多模式参考:<a href="https://kjur.github.io/jsrsasign/api/symbols/KEYUTIL.html">https://kjur.github.io/jsrsasign/api/symbols/KEYUTIL.html</a> * @returns {{privateKey: (string|string|*), publicKey: (string|string|*)}} */export function generateRsaKeyWithPKCS8() { const keyPair = JsRsaSign.KEYUTIL.generateKeypair("RSA", 1024); const privateKey = JsRsaSign.KEYUTIL.getPEM(keyPair.prvKeyObj, "PKCS8PRV"); const publicKey = JsRsaSign.KEYUTIL.getPEM(keyPair.pubKeyObj); return { privateKey, publicKey };}/** * SHA256和RSA加签 * @param privateKey 私钥 * @param msg 加签内容 * @returns {string} Base64编码签名内容 */export function signBySHA256WithRSA(privateKey, msg) { const key = JsRsaSign.KEYUTIL.getKey(privateKey); const signature = new JsRsaSign.KJUR.crypto.Signature({ alg: "SHA256withRSA", }); signature.init(key); signature.updateString(msg); // 签名后的为16进制字符串,这里转换为16进制字符串 return JsRsaSign.hextob64(signature.sign());}/** * SHA256和RSA验签 * @param publicKey 公钥:必须为标准pem格式。如果是PKCS1格式,必须包含-----BEGIN RSA PRIVATE KEY-----,如果是PKCS8格式,必须包含-----BEGIN PRIVATE KEY----- * @param base64SignStr Base64编码签名字符串 * @param msg 原内容 * @returns {boolean} 是否验签通过 */export function verifyBySHA256WithRSA(publicKey, base64SignStr, msg) { const key = JsRsaSign.KEYUTIL.getKey(publicKey); const signature = new JsRsaSign.KJUR.crypto.Signature({ alg: "SHA256withRSA", }); signature.init(key); signature.updateString(msg); // 需要将Base64进制签名字符串转换成16进制字符串 return signature.verify(JsRsaSign.b64tohex(base64SignStr));}3、测试用例

先在前端测试下密钥对生成,RSA加解密、加验签,测试代码如下:

import * as CryptoUtils from '@/utils/cryptoUtils.js';const {privateKey, publicKey} = CryptoUtils.generateRsaKeyWithPKCS8();console.log(`生成的私钥为:\n${privateKey}`);console.log(`生成的公钥为:\n${publicKey}`);const cipherText = CryptoUtils.encryptByRSA(publicKey, "test");console.log(`test加密后的内容为:\n${cipherText}`);const plainText = CryptoUtils.decryptByRSA(privateKey, cipherText);console.log(`解密后的内容为:\n${plainText}`);const signature = CryptoUtils.signBySHA256WithRSA(privateKey, "test");console.log(`生成的签名:\n${signature}`);const isVerified = CryptoUtils.verifyBySHA256WithRSA(publicKey, signature, "test");console.log(`是否验签通过:${isVerified}`);

控制台输出结果为:

生成的私钥为:-----BEGIN PRIVATE KEY-----MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMv1adNmKNw4rtr2Dy92DZ3Nk1SCrGGetlq0sSgLY8bJsByAvP2ZOOiiWq2xDUVu8ZpQfM8v89tjegfrsIUcN/ZVLc68Ric3BIto85oQc9jBz+aCk1rXeNMePkSVqNaC/n4kJ73Y41ZgKAe0GvyqMyUNhk8VZd+QSNATSv+lGep3AgMBAAECgYBoKMvDry98z+HUZsb4iQSJK1xrU1SvgftEtXSnq7Fn6sZquABMTry2aXt/qqTJadAu653hvW5/Av1mICKEyBV3aT4OjQRGPMgp6WhXvQepUIuyi9qlfUVsJy/+J0zGKZeKsCFlwZ2e2j4Un7Bb//pgUfjJrbPtwC7U85oHjtJb6QJBAOdcm07ThSXFbicj2MuX9Gh7geMjncf6aqnrOwUFjO0d5OxfYRAxrZD1GghygHyoJ4ZOHgJ0s6HVEYjg/u6DBdsCQQDhrb4IOVdSew2cW15ft/5DAKUXRRQBfz0OxOs0Uv5k7zqI+YmysWVRGaZgj8oMZ7gYxN1eYNOKTwVjiuwbuyaVAkEA0OGSMpPT1WsvbVT26bFyb1Z6yTihvif/XxPKgFknh/kCcsoWFwnS+1nevBusl181+BLVE0CL4aM9pogEghB3GwJAWJTVzmyTdfCO+xxyAqg5yRrrsiKPI7dJxA5PNA6PhBbSpwkrn1Q6LIcg4y4NZKkhfbdoHK9s2REDUHsrCgd/sQJAALEe+PCXhcHWnwbm4kRFyJCO4dWkii7o28ohTRourlNsoEmiu1+7lt7PY1+C3D+6A4FFCY/HpGM0i0lJue8rZA==-----END PRIVATE KEY-----生成的公钥为:-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL9WnTZijcOK7a9g8vdg2dzZNUgqxhnrZatLEoC2PGybAcgLz9mTjoolqtsQ1FbvGaUHzPL/PbY3oH67CFHDf2VS3OvEYnNwSLaPOaEHPYwc/mgpNa13jTHj5ElajWgv5+JCe92ONWYCgHtBr8qjMlDYZPFWXfkEjQE0r/pRnqdwIDAQAB-----END PUBLIC KEY-----test加密后的内容为:KjcaDKLnBbvxRzuKMysqoz9MHRXCUNIH67+XDiFGTJbM8Rjw4Cei0CzjAPjk2jgAR37Kgh6lX2+Xg8AI9wEmzWr08bt8i2FFxVMrcfOCs5zI1y+2T7G9034f5b0gNx/Pc4dDz+1k453vo0AhCC0vrtb1OfbsRu5oOFns0TqoAMY=解密后的内容为:test生成的签名:t0koTqhiWmq/wEvI/ieJq5kZj7Dc/limF7GNVtHNLReqLVBXZvAZrOIwdqda7LBHBSHcRZBISWtbuyDiOR9KFPObrOgOEUOdfACUMzjWKCtO8ZgcQ+U02FyGeeH2rT9rJEJAXDEM+Kn3+H4ZdbrUFPY3jQRl535wnK9CLpxqAG4=是否验签通过:true

备注:为什么在前端生成PKCS#8格式密钥呢? 因为在Java中非对称加解密、加验签都是用的PKCS#8,PKCS#1格式密钥需要转换成PKCS#8。

五、Java后端RSA加解密、加验签1、CryptoUtils工具类封装import com.universe.crypto.CryptoUtils.Algorithm.Encryption;import com.universe.crypto.CryptoUtils.Algorithm.Signing;import lombok.AllArgsConstructor;import lombok.Data;import lombok.Getter;import lombok.NoArgsConstructor;import org.apache.commons.lang3.StringUtils;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.NoSuchPaddingException;import javax.crypto.SecretKey;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import java.nio.charset.Charset;import java.nio.charset.StandardCharsets;import java.security.Key;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.PrivateKey;import java.security.PublicKey;import java.security.Signature;import java.security.spec.InvalidKeySpecException;import java.security.spec.KeySpec;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Base64;import java.util.Base64.Decoder;import java.util.Base64.Encoder;import java.util.HashMap;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;/** * 支持AES、DES、RSA加密、数字签名以及生成对称密钥和非对称密钥对 */public class CryptoUtils {private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;private static final Encoder BASE64_ENCODER = Base64.getEncoder();private static final Decoder BASE64_DECODER = Base64.getDecoder();private static final Map<Algorithm, KeyFactory> KEY_FACTORY_CACHE = new ConcurrentHashMap<>();private static final Map<Algorithm, Cipher> CIPHER_CACHE = new HashMap<>();/** * 生成对称密钥,目前支持的算法有AES、DES * @param algorithm * @return * @throws NoSuchAlgorithmException */public static String generateSymmetricKey(Algorithm algorithm) throws NoSuchAlgorithmException {KeyGenerator generator = KeyGenerator.getInstance(algorithm.getName());generator.init(algorithm.getKeySize());SecretKey secretKey = generator.generateKey();return BASE64_ENCODER.encodeToString(secretKey.getEncoded());}/** * 生成非对称密钥对,目前支持的算法有RSA、DSA。备注:默认生成的密钥格式为PKCS8 * @param algorithm * @return * @throws NoSuchAlgorithmException */public static AsymmetricKeyPair generateAsymmetricKeyPair(Algorithm algorithm) throws NoSuchAlgorithmException {KeyPairGenerator generator = KeyPairGenerator.getInstance(algorithm.getName());generator.initialize(algorithm.getKeySize());KeyPair keyPair = generator.generateKeyPair();String publicKey = BASE64_ENCODER.encodeToString(keyPair.getPublic().getEncoded());String privateKey = BASE64_ENCODER.encodeToString(keyPair.getPrivate().getEncoded());return new AsymmetricKeyPair(publicKey, privateKey);}public static String encryptByRSA(String publicKeyText, String plainText) throws Exception {return encryptAsymmetrically(publicKeyText, plainText, Encryption.RSA_ECB_PKCS1);}public static String decryptByRSA(String privateKeyText, String ciphertext) throws Exception {return decryptAsymmetrically(privateKeyText, ciphertext, Encryption.RSA_ECB_PKCS1);}/** * SHA1签名算法和DSA加密算法结合使用生成数字签名 * @param privateKeyText * @param msg * @return 数字签名 * @throws Exception */public static String signBySHA1WithDSA(String privateKeyText, String msg) throws Exception {return doSign(privateKeyText, msg, Encryption.DSA, Signing.SHA1WithDSA);}/** * SHA1签名算法和RSA加密算法结合使用生成数字签名 * @param privateKeyText 私钥 * @param msg 待加签内容 * @return 数字签名 * @throws Exception */public static String signBySHA1WithRSA(String privateKeyText, String msg) throws Exception {return doSign(privateKeyText, msg, Encryption.RSA_ECB_PKCS1, Signing.SHA1WithRSA);}/** * SHA256签名算法和RSA加密算法结合使用生成数字签名 * @param privateKeyText 私钥 * @param msg 待加签内容 * @return 数字签名 * @throws Exception */public static String signBySHA256WithRSA(String privateKeyText, String msg) throws Exception {return doSign(privateKeyText, msg, Encryption.RSA_ECB_PKCS1, Signing.SHA256WithRSA);}/** * SHA1签名算法和DSA加密算法检验数字签名 * @param publicKeyText 公钥 * @param msg 待验签内容 * @param signatureText 数字 * @return 检验是否成功 * @throws Exception */public static boolean verifyBySHA1WithDSA(String publicKeyText, String msg, String signatureText) throws Exception {return doVerify(publicKeyText, msg, signatureText, Encryption.DSA, Signing.SHA1WithDSA);}/** * SHA1签名算法和RSA加密算法检验数字签名 * @param publicKeyText 公钥 * @param msg 待验签内容 * @param signatureText 签名 * @return 校验是否成功 * @throws Exception */public static boolean verifyBySHA1WithRSA(String publicKeyText, String msg, String signatureText) throws Exception {return doVerify(publicKeyText, msg, signatureText, Encryption.RSA_ECB_PKCS1, Signing.SHA1WithRSA);}/** * SHA256签名算法和RSA加密算法检验数字签名 * @param publicKeyText 公钥 * @param msg 待验签内容 * @param signatureText 签名 * @return 校验是否成功 * @throws Exception */public static boolean verifyBySHA256WithRSA(String publicKeyText, String msg, String signatureText) throws Exception {return doVerify(publicKeyText, msg, signatureText, Encryption.RSA_ECB_PKCS1, Signing.SHA256WithRSA);}/** * 对称加密 * @param secretKey 密钥 * @param iv 加密向量,只有CBC模式才支持,如果是CBC则必传 * @param plainText 明文 * @param algorithm 对称加密算法,如AES、DES * @return * @throws Exception */public static String encryptSymmetrically(String secretKey, String iv, String plainText, Algorithm algorithm) throws Exception {SecretKey key = decodeSymmetricKey(secretKey, algorithm);IvParameterSpec ivParameterSpec = StringUtils.isBlank(iv) ? null : decodeIv(iv);byte[] plainTextInBytes = plainText.getBytes(DEFAULT_CHARSET);byte[] ciphertextInBytes = transform(algorithm, Cipher.ENCRYPT_MODE, key, ivParameterSpec, plainTextInBytes);return BASE64_ENCODER.encodeToString(ciphertextInBytes);}/** * 对称解密 * @param secretKey 密钥 * @param iv 加密向量,只有CBC模式才支持,如果是CBC则必传 * @param ciphertext 密文 * @param algorithm 对称加密算法,如AES、DES * @return * @throws Exception */public static String decryptSymmetrically(String secretKey, String iv, String ciphertext, Algorithm algorithm) throws Exception {SecretKey key = decodeSymmetricKey(secretKey, algorithm);IvParameterSpec ivParameterSpec = StringUtils.isBlank(iv) ? null : decodeIv(iv);byte[] ciphertextInBytes = BASE64_DECODER.decode(ciphertext);byte[] plainTextInBytes = transform(algorithm, Cipher.DECRYPT_MODE, key, ivParameterSpec, ciphertextInBytes);return new String(plainTextInBytes, DEFAULT_CHARSET);}/** * 非对称加密 * @param publicKeyText 公钥 * @param plainText 明文 * @param algorithm 非对称加密算法 * @return * @throws Exception */public static String encryptAsymmetrically(String publicKeyText, String plainText, Algorithm algorithm) throws Exception {PublicKey publicKey = regeneratePublicKey(publicKeyText, algorithm);byte[] plainTextInBytes = plainText.getBytes(DEFAULT_CHARSET);byte[] ciphertextInBytes = transform(algorithm, Cipher.ENCRYPT_MODE, publicKey, plainTextInBytes);return BASE64_ENCODER.encodeToString(ciphertextInBytes);}/** * 非对称解密 * @param privateKeyText 私钥 * @param ciphertext 密文 * @param algorithm 非对称加密算法 * @return * @throws Exception */public static String decryptAsymmetrically(String privateKeyText, String ciphertext, Algorithm algorithm) throws Exception {PrivateKey privateKey = regeneratePrivateKey(privateKeyText, algorithm);byte[] ciphertextInBytes = BASE64_DECODER.decode(ciphertext);byte[] plainTextInBytes = transform(algorithm, Cipher.DECRYPT_MODE, privateKey, ciphertextInBytes);return new String(plainTextInBytes, DEFAULT_CHARSET);}/** * 生成数字签名 * @param privateKeyText 私钥 * @param msg 传输的数据 * @param encryptionAlgorithm 加密算法,见Algorithm中的加密算法 * @param signatureAlgorithm 签名算法,见Algorithm中的签名算法 * @return 数字签名 * @throws Exception */public static String doSign(String privateKeyText, String msg, Algorithm encryptionAlgorithm, Algorithm signatureAlgorithm)throws Exception {PrivateKey privateKey = regeneratePrivateKey(privateKeyText, encryptionAlgorithm);// Signature只支持签名算法Signature signature = Signature.getInstance(signatureAlgorithm.getName());signature.initSign(privateKey);signature.update(msg.getBytes(DEFAULT_CHARSET));byte[] signatureInBytes = signature.sign();return BASE64_ENCODER.encodeToString(signatureInBytes);}/** * 数字签名验证 * @param publicKeyText 公钥 * @param msg 传输的数据 * @param signatureText 数字签名 * @param encryptionAlgorithm 加密算法,见Algorithm中的加密算法 * @param signatureAlgorithm 签名算法,见Algorithm中的签名算法 * @return 校验是否成功 * @throws Exception */public static boolean doVerify(String publicKeyText, String msg, String signatureText, Algorithm encryptionAlgorithm,Algorithm signatureAlgorithm) throws Exception {PublicKey publicKey = regeneratePublicKey(publicKeyText, encryptionAlgorithm);Signature signature = Signature.getInstance(signatureAlgorithm.getName());signature.initVerify(publicKey);signature.update(msg.getBytes(DEFAULT_CHARSET));return signature.verify(BASE64_DECODER.decode(signatureText));}/** * 将密钥进行Base64位解码,重新生成SecretKey实例 * @param secretKey 密钥 * @param algorithm 算法 * @return */private static SecretKey decodeSymmetricKey(String secretKey, Algorithm algorithm) {byte[] key = BASE64_DECODER.decode(secretKey);return new SecretKeySpec(key, algorithm.getName());}private static IvParameterSpec decodeIv(String iv) {byte[] ivInBytes = BASE64_DECODER.decode(iv);return new IvParameterSpec(ivInBytes);}private static PublicKey regeneratePublicKey(String publicKeyText, Algorithm algorithm)throws NoSuchAlgorithmException, InvalidKeySpecException {byte[] keyInBytes = BASE64_DECODER.decode(publicKeyText);KeyFactory keyFactory = getKeyFactory(algorithm);// 公钥必须使用RSAPublicKeySpec或者X509EncodedKeySpecKeySpec publicKeySpec = new X509EncodedKeySpec(keyInBytes);PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);return publicKey;}private static PrivateKey regeneratePrivateKey(String key, Algorithm algorithm) throws Exception {byte[] keyInBytes = BASE64_DECODER.decode(key);KeyFactory keyFactory = getKeyFactory(algorithm);// 私钥必须使用RSAPrivateCrtKeySpec或者PKCS8EncodedKeySpecKeySpec privateKeySpec = new PKCS8EncodedKeySpec(keyInBytes);PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);return privateKey;}private static KeyFactory getKeyFactory(Algorithm algorithm) throws NoSuchAlgorithmException {KeyFactory keyFactory = KEY_FACTORY_CACHE.get(algorithm);if (keyFactory == null) {keyFactory = KeyFactory.getInstance(algorithm.getName());KEY_FACTORY_CACHE.put(algorithm, keyFactory);}return keyFactory;}private static byte[] transform(Algorithm algorithm, int mode, Key key, byte[] msg) throws Exception {return transform(algorithm, mode, key, null, msg);}private static byte[] transform(Algorithm algorithm, int mode, Key key, IvParameterSpec iv, byte[] msg) throws Exception {Cipher cipher = CIPHER_CACHE.get(algorithm);// double check,减少上下文切换if (cipher == null) {synchronized (CryptoUtils.class) {if ((cipher = CIPHER_CACHE.get(algorithm)) == null) {cipher = determineWhichCipherToUse(algorithm);CIPHER_CACHE.put(algorithm, cipher);}cipher.init(mode, key, iv);return cipher.doFinal(msg);}}synchronized (CryptoUtils.class) {cipher.init(mode, key, iv);return cipher.doFinal(msg);}}private static Cipher determineWhichCipherToUse(Algorithm algorithm) throws NoSuchAlgorithmException, NoSuchPaddingException {Cipher cipher;String transformation = algorithm.getTransformation();// 官方推荐的transformation使用algorithm/mode/padding组合,SunJCE使用ECB作为默认模式,使用PKCS5Padding作为默认填充if (StringUtils.isNotEmpty(transformation)) {cipher = Cipher.getInstance(transformation);} else {cipher = Cipher.getInstance(algorithm.getName());}return cipher;}/** * 算法分为加密算法和签名算法,更多算法实现见:<br/> * <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#impl">jdk8中的标准算法</a> */public static class Algorithm {public interface Encryption {Algorithm AES_ECB_PKCS5 = new Algorithm("AES", "AES/ECB/PKCS5Padding", 128);Algorithm AES_CBC_PKCS5 = new Algorithm("AES", "AES/CBC/PKCS5Padding", 128);Algorithm DES_ECB_PKCS5 = new Algorithm("DES", "DES/ECB/PKCS5Padding", 56);Algorithm DES_CBC_PKCS5 = new Algorithm("DES", "DES/CBC/PKCS5Padding", 56);Algorithm RSA_ECB_PKCS1 = new Algorithm("RSA", "RSA/ECB/PKCS1Padding", 1024);Algorithm DSA = new Algorithm("DSA", 1024);}public interface Signing {Algorithm SHA1WithDSA = new Algorithm("SHA1withDSA", 1024);Algorithm SHA1WithRSA = new Algorithm("SHA1WithRSA", 2048);Algorithm SHA256WithRSA = new Algorithm("SHA256WithRSA", 2048);}@Getterprivate String name;@Getterprivate String transformation;@Getterprivate int keySize;public Algorithm(String name, int keySize) {this(name, null, keySize);}public Algorithm(String name, String transformation, int keySize) {this.name = name;this.transformation = transformation;this.keySize = keySize;}}@Data@NoArgsConstructor@AllArgsConstructorpublic static class AsymmetricKeyPair {private String publicKey;private String privateKey;}}2、测试用例AsymmetricKeyPair keyPair = CryptoUtils.generateAsymmetricKeyPair(Encryption.RSA_ECB_PKCS1);String privateKey = keyPair.getPrivateKey();String publicKey = keyPair.getPublicKey();System.out.println("生成的私钥为:\n" + privateKey);System.out.println("生成的公钥为:\n" + publicKey);String cipherText = CryptoUtils.encryptByRSA(publicKey, "test");String plainText = CryptoUtils.decryptByRSA(privateKey, cipherText);System.out.println("test加密后的密文为:\n" + cipherText);System.out.println("解密后的明文为:" + plainText);String signature = CryptoUtils.signBySHA256WithRSA(privateKey, "message");boolean isVerified = CryptoUtils.verifyBySHA256WithRSA(publicKey, "message", signature);System.out.println("message加签后的签名为:" + signature);System.out.println("验签是否通过:" + isVerified);

控制台输出如下:

生成的私钥为:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAL4TdBqlxJByJURSqNzthP18t2Q6tzmdwfoTJka0yy/DjEL1/mBPdcygwWBfVYLBvwuBUOyG4pbf/de0pmgc9b7+SwNqqpHtmLxaEqW3ebovm0R2UFom0OS/5X5pdWNKuKDTCpP2xC1JSfRqS+7WNgFEhCK7hRWBzIpifXvLzZNtAgMBAAECgYAcjOd/qS6hU8PtQ01CAhtbyAPz9i3XZa7hVUcGj9mFTyYeWLzg0o6rMepaA3fgsCF2JPJ21LvsVbDXWbc1JER1LYIWYZ79XnYZQgezmfqeSFx+CJkndRZ/qXGnf/1EUJFjEafbkXGRvnv05B4QHBQGn3gfIa2xsLw2r3Yf8M5/gQJBAOXgqeH5yyJ6iNIw5S8EAR7VAUMPteQ/JqQ6l+wYcesj/prqhwRX4x2m/wKh6qM2zZcFLMujYTyJsIQkzmOkFXkCQQDTrO1bnO84dbEVOUv73g0J1jg/3EIbt8uh7T4Iu82/9ycUyQ5D8oANh53rfPf5DXycXWXRlu2gwGvsyNRW1LSVAkEAnYs6go/Cgw+9g2hVOcKhzfKnmcFDpHkPT5CEnB8ou8GAdcVz4SsmkSTpMnGrsE4X2n+Gcs23D1lCK15aQHms6QJBAJ/8GmXcph25Lj9JT/msaZReuaLimYCTmK/pPLKjJy4I4hveng6S8V/IeX4rtMwi+mTAXp1bgny2EpwjagG6wEUCQH9ap3J9fh8UicEPD1LO/GUTTNXuPiwWOcNgetntrjPAJx5b0bf6hEJOyEHtIsuSuzAD8G41o2tpsefact3EwzY=生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+E3QapcSQciVEUqjc7YT9fLdkOrc5ncH6EyZGtMsvw4xC9f5gT3XMoMFgX1WCwb8LgVDshuKW3/3XtKZoHPW+/ksDaqqR7Zi8WhKlt3m6L5tEdlBaJtDkv+V+aXVjSrig0wqT9sQtSUn0akvu1jYBRIQiu4UVgcyKYn17y82TbQIDAQABtest加密后的密文为:EA19/wkHbdXTc8sfLFhmnp/MWW3PLx2LeYFHWFNdhvY38+Zoa4Ci8HJw8okkxzTfsSkgsiybMaz82rwF9lfcuEWzjbuGeVOvdkI0p/Cv+PDfikMYwOsxA7OqBJ/Hktn25l/ryEv7TxYlMFQ48jB0KPw/0Ivec9qfX2pgnyBl7WM=解密后的明文为:testmessage加签后的签名为:AByFyRoc/321db16voe9NQaicwkscTOGjBZGefWzB7dMadWXBtUPIK3CUXADLiiesehgAAcDbl06qVz++x/6xeWPCK2ucCfn9dFybZfmAIsn+3TATuDQIFvz/m2cHQAuH9fkmiGgMPOVY/VcILwri3RETuQ+wz4YSmP89o1cFqk=验签是否通过:true

六、前后端加解密、加验签交互测试1、前端加密,后端解密

这里我们用前端生成的密钥对做测试。

(1) 前端代码import * as CryptoUtils from '@/utils/cryptoUtils.js';const {privateKey, publicKey} = CryptoUtils.generateRsaKeyWithPKCS8();console.log(`生成的私钥为:\n${privateKey}`);console.log(`生成的公钥为:\n${publicKey}`);const cipherText = CryptoUtils.encryptByRSA(publicKey, "test");console.log(`test加密后的内容为:\n${cipherText}`);

控制台输出:

生成的私钥为:-----BEGIN PRIVATE KEY-----MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMv1adNmKNw4rtr2Dy92DZ3Nk1SCrGGetlq0sSgLY8bJsByAvP2ZOOiiWq2xDUVu8ZpQfM8v89tjegfrsIUcN/ZVLc68Ric3BIto85oQc9jBz+aCk1rXeNMePkSVqNaC/n4kJ73Y41ZgKAe0GvyqMyUNhk8VZd+QSNATSv+lGep3AgMBAAECgYBoKMvDry98z+HUZsb4iQSJK1xrU1SvgftEtXSnq7Fn6sZquABMTry2aXt/qqTJadAu653hvW5/Av1mICKEyBV3aT4OjQRGPMgp6WhXvQepUIuyi9qlfUVsJy/+J0zGKZeKsCFlwZ2e2j4Un7Bb//pgUfjJrbPtwC7U85oHjtJb6QJBAOdcm07ThSXFbicj2MuX9Gh7geMjncf6aqnrOwUFjO0d5OxfYRAxrZD1GghygHyoJ4ZOHgJ0s6HVEYjg/u6DBdsCQQDhrb4IOVdSew2cW15ft/5DAKUXRRQBfz0OxOs0Uv5k7zqI+YmysWVRGaZgj8oMZ7gYxN1eYNOKTwVjiuwbuyaVAkEA0OGSMpPT1WsvbVT26bFyb1Z6yTihvif/XxPKgFknh/kCcsoWFwnS+1nevBusl181+BLVE0CL4aM9pogEghB3GwJAWJTVzmyTdfCO+xxyAqg5yRrrsiKPI7dJxA5PNA6PhBbSpwkrn1Q6LIcg4y4NZKkhfbdoHK9s2REDUHsrCgd/sQJAALEe+PCXhcHWnwbm4kRFyJCO4dWkii7o28ohTRourlNsoEmiu1+7lt7PY1+C3D+6A4FFCY/HpGM0i0lJue8rZA==-----END PRIVATE KEY-----生成的公钥为:-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL9WnTZijcOK7a9g8vdg2dzZNUgqxhnrZatLEoC2PGybAcgLz9mTjoolqtsQ1FbvGaUHzPL/PbY3oH67CFHDf2VS3OvEYnNwSLaPOaEHPYwc/mgpNa13jTHj5ElajWgv5+JCe92ONWYCgHtBr8qjMlDYZPFWXfkEjQE0r/pRnqdwIDAQAB-----END PUBLIC KEY-----test加密后的内容为:KjcaDKLnBbvxRzuKMysqoz9MHRXCUNIH67+XDiFGTJbM8Rjw4Cei0CzjAPjk2jgAR37Kgh6lX2+Xg8AI9wEmzWr08bt8i2FFxVMrcfOCs5zI1y+2T7G9034f5b0gNx/Pc4dDz+1k453vo0AhCC0vrtb1OfbsRu5oOFns0TqoAMY=解密后的内容为:test(2) 后端代码String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMv1adNmKNw4rtr2Dy92DZ3Nk1SCrGGetlq0sSgLY8bJsByAvP2ZOOiiWq2xDUVu8ZpQfM8v89tjegfrsIUcN/ZVLc68Ric3BIto85oQc9jBz+aCk1rXeNMePkSVqNaC/n4kJ73Y41ZgKAe0GvyqMyUNhk8VZd+QSNATSv+lGep3AgMBAAECgYBoKMvDry98z+HUZsb4iQSJK1xrU1SvgftEtXSnq7Fn6sZquABMTry2aXt/qqTJadAu653hvW5/Av1mICKEyBV3aT4OjQRGPMgp6WhXvQepUIuyi9qlfUVsJy/+J0zGKZeKsCFlwZ2e2j4Un7Bb//pgUfjJrbPtwC7U85oHjtJb6QJBAOdcm07ThSXFbicj2MuX9Gh7geMjncf6aqnrOwUFjO0d5OxfYRAxrZD1GghygHyoJ4ZOHgJ0s6HVEYjg/u6DBdsCQQDhrb4IOVdSew2cW15ft/5DAKUXRRQBfz0OxOs0Uv5k7zqI+YmysWVRGaZgj8oMZ7gYxN1eYNOKTwVjiuwbuyaVAkEA0OGSMpPT1WsvbVT26bFyb1Z6yTihvif/XxPKgFknh/kCcsoWFwnS+1nevBusl181+BLVE0CL4aM9pogEghB3GwJAWJTVzmyTdfCO+xxyAqg5yRrrsiKPI7dJxA5PNA6PhBbSpwkrn1Q6LIcg4y4NZKkhfbdoHK9s2REDUHsrCgd/sQJAALEe+PCXhcHWnwbm4kRFyJCO4dWkii7o28ohTRourlNsoEmiu1+7lt7PY1+C3D+6A4FFCY/HpGM0i0lJue8rZA==";String cipherText = "KjcaDKLnBbvxRzuKMysqoz9MHRXCUNIH67+XDiFGTJbM8Rjw4Cei0CzjAPjk2jgAR37Kgh6lX2+Xg8AI9wEmzWr08bt8i2FFxVMrcfOCs5zI1y+2T7G9034f5b0gNx/Pc4dDz+1k453vo0AhCC0vrtb1OfbsRu5oOFns0TqoAMY=";// 解密后的明文应该为testString plainText = CryptoUtils.decryptByRSA(privateKey, cipherText);System.out.println("解密后的明文为:" + plainText);

控制台输出如下:

解密后的明文为:test

备注:

从前端复制过来的密钥需要去掉-----BEGIN PRIVATE KEY-----前缀。从前端复制过来的密钥带有换行,记得去掉中间的换行符。2、后端加密,前端解密

这里我们用后端生成的密钥对做测试。

(1) 后端代码AsymmetricKeyPair keyPair = CryptoUtils.generateAsymmetricKeyPair(Encryption.RSA_ECB_PKCS1);String privateKey = keyPair.getPrivateKey();String publicKey = keyPair.getPublicKey();System.out.println("生成的私钥为:\n" + privateKey);System.out.println("生成的公钥为:\n" + publicKey);String cipherText = CryptoUtils.encryptByRSA(publicKey, "test");System.out.println("test加密后的内容为:\n" + cipherText);

控制台输出为:

生成的私钥为:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJPh8WiDo3dhKHW9w86D4DX84pHAG03PIeOHCSezbyKeyKsuHA3qayGJ7JqQgWis557uawz95/EbBzzwmO0oy+l16fkiRXcRppU/UbW6PUBbIpJNqCjnKcw+DA5UXVDmIv0xXOP34jlnkY1DxnimqMAkgut8gncgdFxO0ap0us6lAgMBAAECgYBzlVpQ/OqMCRVNiYd8ZxicOc6Aaq0skKOFKWsfa6CGZ6KiIMTun3UiXqHeYOm0fcf/MYvcOKvLh/uNRuPQIV3WKAWJ6r+dXQ+LjzmrH4QDMcmkMn0OKxxbe56MASPWka7/08GLiE1FJLDo8DEkBQnlDHqnt4e7BoZSgYVhWv52AQJBAMcr0O7xiB/Ge9aQzqYQJvdQ4JI53pM0lEx5HPzQjbrMjC1flb572js1ajKckkuTX+nxzyTzC3JtfvGCcMqaaoECQQC+E9LoSfZZHpVFCx4ZIh2VgzrGYnelktb6MenILhdji2j9i6ZyAqyg8TjL+W9/kAKnaNAV2j6GF8/bOTX0UGolAkAcUWiFcKXwDqJw4WngRo+jvkYPxFaXC3TCYr3yXByqoIaVtO9vg+CFZpTQ2V4bjLqoYo8XK89G17ai0+8Bf28BAkA+BGvRHKjDJSZg86KrYqUybjHUHraZEFMSKQz1IozBDvB/oXv6QQMgM/RrIQSPI2aqRpl2N9IkoEpSZdVD1KT9AkBtoz4Eg3Nuy1XdCCrTqTMioY0hP74xCcgURpooxmL2xhNUYu6PJr+g4lkaiq8e/2Cr0ZQlps/pEDgaPdHDf3Et生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCT4fFog6N3YSh1vcPOg+A1/OKRwBtNzyHjhwkns28insirLhwN6mshieyakIForOee7msM/efxGwc88JjtKMvpden5IkV3EaaVP1G1uj1AWyKSTago5ynMPgwOVF1Q5iL9MVzj9+I5Z5GNQ8Z4pqjAJILrfIJ3IHRcTtGqdLrOpQIDAQABtest加密后的内容为:RgJxG+VSizKgfLnXjsqzTl9h0cUzm460EyHhdL3/qZLNbd6IVcU1Am+OOsbFd9W8GtNhJiCERybgjCucr4c3/EQLXtF8vNHVMFp9ycDW4T+8FMmFQn0f/+oJ7/i9uEoNd9W8nWJcSRHuTw1+rl4Mc7KnmwvdaTV2ZLOxBG6oAK8=(2) 前端代码const privateKey = `MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJPh8WiDo3dhKHW9w86D4DX84pHAG03PIeOHCSezbyKeyKsuHA3qayGJ7JqQgWis557uawz95/EbBzzwmO0oy+l16fkiRXcRppU/UbW6PUBbIpJNqCjnKcw+DA5UXVDmIv0xXOP34jlnkY1DxnimqMAkgut8gncgdFxO0ap0us6lAgMBAAECgYBzlVpQ/OqMCRVNiYd8ZxicOc6Aaq0skKOFKWsfa6CGZ6KiIMTun3UiXqHeYOm0fcf/MYvcOKvLh/uNRuPQIV3WKAWJ6r+dXQ+LjzmrH4QDMcmkMn0OKxxbe56MASPWka7/08GLiE1FJLDo8DEkBQnlDHqnt4e7BoZSgYVhWv52AQJBAMcr0O7xiB/Ge9aQzqYQJvdQ4JI53pM0lEx5HPzQjbrMjC1flb572js1ajKckkuTX+nxzyTzC3JtfvGCcMqaaoECQQC+E9LoSfZZHpVFCx4ZIh2VgzrGYnelktb6MenILhdji2j9i6ZyAqyg8TjL+W9/kAKnaNAV2j6GF8/bOTX0UGolAkAcUWiFcKXwDqJw4WngRo+jvkYPxFaXC3TCYr3yXByqoIaVtO9vg+CFZpTQ2V4bjLqoYo8XK89G17ai0+8Bf28BAkA+BGvRHKjDJSZg86KrYqUybjHUHraZEFMSKQz1IozBDvB/oXv6QQMgM/RrIQSPI2aqRpl2N9IkoEpSZdVD1KT9AkBtoz4Eg3Nuy1XdCCrTqTMioY0hP74xCcgURpooxmL2xhNUYu6PJr+g4lkaiq8e/2Cr0ZQlps/pEDgaPdHDf3Et`;const cipherText = `RgJxG+VSizKgfLnXjsqzTl9h0cUzm460EyHhdL3/qZLNbd6IVcU1Am+OOsbFd9W8GtNhJiCERybgjCucr4c3/EQLXtF8vNHVMFp9ycDW4T+8FMmFQn0f/+oJ7/i9uEoNd9W8nWJcSRHuTw1+rl4Mc7KnmwvdaTV2ZLOxBG6oAK8=`;const plainText = CryptoUtils.decryptByRSA(privateKey, cipherText);console.log(`解密后的内容为:${plainText}`);

控制台输出:

解密后的内容为:test3、前端加签,后端验签

这里我们用前端生成的密钥对做测试。

(1) 前端代码const {privateKey, publicKey} = CryptoUtils.generateRsaKeyWithPKCS8();console.log(`生成的私钥为:\n${privateKey}`);console.log(`生成的公钥为:\n${publicKey}`);const signature = CryptoUtils.signBySHA256WithRSA(privateKey, "test");console.log(`生成的签名:\n${signature}`);

控制台输出如下:

生成的私钥为:-----BEGIN PRIVATE KEY-----MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALxzJ+U/N/lE+AZOzMbzx+5WrWDu31oKlH+jth54APGHY+Cmqvi0dUeuSbv238tkem95GTy1kQRz9CMBWvvVdNYC78E8maBaMKb+GZKVIScZ6eo8gkXxEoB7a3/y6a8L/SpQGgaI78JsnVGJijf+GaGtfbl+dIQMxIc6gbNZOM/PAgMBAAECgYEAiAKE1Mwf1eSVLdhJq33e2oHseH1u7kmci9LYan0qESgqScWAuCdmTenYhbTUKLPIOhQoxsw0cgZOOcWMqR2SSHW/CK0Ql/5jP94wyX5Gw62jFXpLTVKQ1piiNjoujTKOsnkdtfh/JnjdeWh7GEcHhGGwyin0F1aHZgex4MkG0EECQQDsqJJxESC5QjZl5f6EDIbkSznmeV0IPfgIs8uN1QIDjFbS97QhClSrsev4LXxuGkltOpWbJUkG+nmjZhDPnV1nAkEAy9nzQndYxiv/XLpd+Id2pB+SBRs/panFFEIoEEb4UoY7QPLfQ6ZOQQ9+vC5r1tWQtIhwiEjhYaGhnBZ1TASRWQJBAOADNRMnxlT2Uu2jhobSIMFqX7VEvgY2Ollqb0yjC1P2fJ0X8X6w+7LGKPnzfGvwH/7vzHteEME1SPydeV48tBMCQQCtCsZElar2DkMnI8zBO7yqdWIuk4LjzclN+RqpNpV0+B00dPaxJmsnL1AVzhIcvA2qMmfUSImJpvrY1PedIAOBAkAvjVU03USMjvv5iudWyqqRy8Q9s2qeWYEiv+bFeLExiqGj9kmOkIfPcm96ElZr1F7PlaQbwj2A+D2oaQGcQqUm-----END PRIVATE KEY-----生成的公钥为:-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8cyflPzf5RPgGTszG88fuVq1g7t9aCpR/o7YeeADxh2Pgpqr4tHVHrkm79t/LZHpveRk8tZEEc/QjAVr71XTWAu/BPJmgWjCm/hmSlSEnGenqPIJF8RKAe2t/8umvC/0qUBoGiO/CbJ1RiYo3/hmhrX25fnSEDMSHOoGzWTjPzwIDAQAB-----END PUBLIC KEY-----生成的签名:Q9Mtq3gxi2YJ07FQtbry5zxGljomzKQNewhj10Ba10b3roAAdQUzqd+QyP7rqARdPQgt0ClDgvtaL2TNYLc4URh7E3Kgx8T6pSFlPnU/b3cfCoVRPrr/gJBrsCkbNMITNXpVQpwIYe3P1z+OrCUHuaQR82yCVUz3y43oOiE6qIY=(2) 后端代码String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8cyflPzf5RPgGTszG88fuVq1g7t9aCpR/o7YeeADxh2Pgpqr4tHVHrkm79t/LZHpveRk8tZEEc/QjAVr71XTWAu/BPJmgWjCm/hmSlSEnGenqPIJF8RKAe2t/8umvC/0qUBoGiO/CbJ1RiYo3/hmhrX25fnSEDMSHOoGzWTjPzwIDAQAB";String signature = "Q9Mtq3gxi2YJ07FQtbry5zxGljomzKQNewhj10Ba10b3roAAdQUzqd+QyP7rqARdPQgt0ClDgvtaL2TNYLc4URh7E3Kgx8T6pSFlPnU/b3cfCoVRPrr/gJBrsCkbNMITNXpVQpwIYe3P1z+OrCUHuaQR82yCVUz3y43oOiE6qIY=";boolean isVerified = CryptoUtils.verifyBySHA256WithRSA(publicKey, "test", signature);System.out.println("是否验签通过:" + isVerified);

控制台输出:

是否验签通过:true4、后端加签,前端验签

这里我们用后端生成的密钥对做测试。

(1) 后端代码AsymmetricKeyPair keyPair = CryptoUtils.generateAsymmetricKeyPair(Encryption.RSA_ECB_PKCS1);String privateKey = keyPair.getPrivateKey();String publicKey = keyPair.getPublicKey();System.out.println("生成的私钥为:\n" + privateKey);System.out.println("生成的公钥为:\n" + publicKey);String signature = CryptoUtils.signBySHA256WithRSA(privateKey, "test");System.out.println("生成的签名为:\n" + signature);

控制台输出如下:

生成的私钥为:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKx1iT0ObyRKC06wf+WN1v9LTQwd68X1b8U5+ZAh9Qf7m77HiQtLg1y91v0b70Dr/HRP7juGLFTnK5+NJMcjGNqDfDFqCQtA3eam2UABbwHS76qRFQbSg5QKApvDcfOZtqWmbwwSDMkI5GnYKbSO3EZZCYBBXzplabKQCKcmGKOjAgMBAAECgYAovOb7RkKYxuje4LCFkDjeO3Jqz1KXg3+wjh5Wnr7b8OJ8cXP8+AyCxtFXHtcoddY/v3XeF7a3I5hZayTp6W+AI1OTYhWs9Eqas8B7bNV2rJPFnK9nTiF727bgptJfGuUG8mYxRzIQleHoWqpV9i/ttcEUPM4GGcIfpnwb16NBAQJBANPBLuTCyeDbSW79MmsiTNUeCnljM/UQYUfIpygviNX1iVbsh1lI/l85bN47niIt66j4c5MPOKJOv2Hf3yYqvIECQQDQfmzfLo7deqsizkJAFKggH99ab24iC+VEDtsHlsl212NC36xenoWwuIcP8fJd1UyWY5lwzzCdBKsrt0UeSd4jAkBwrv3AWHPLh4YFXRHGdyNBydGzFPpiL8xEwd9KADml+hqSuh2wgqpyjAGGJV2aPKuKaGRAXro5jQRFFjgOfHGBAkEAsq22ViqLa0nmgmSrqElLsIRAITvf8bOqHwJwOXfDXmLGgZg5G7nVLxdlQIgEQuA6y6O960zVB6vpmgRtasC5awJBAJkwLiKikvPxC8vwhZvkjr+UrbDorUKcuCyDVYxXsSNW8SNs+AV54wEI1Mem5LOhNPKbum6bwwfTf74gC/l4jtw=生成的公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsdYk9Dm8kSgtOsH/ljdb/S00MHevF9W/FOfmQIfUH+5u+x4kLS4Ncvdb9G+9A6/x0T+47hixU5yufjSTHIxjag3wxagkLQN3mptlAAW8B0u+qkRUG0oOUCgKbw3Hzmbalpm8MEgzJCORp2Cm0jtxGWQmAQV86ZWmykAinJhijowIDAQAB生成的签名为:JQ2FWaAbHWIkl4uSIxyMNbARFzSNKc7mOtXidm7hCRN85D8DVgZll02DYcWRSnn/ejOOxOrEPF8AcYHWx1repHh/jHcwv2focjF3Yne7NkQ4yGvgILDD2s1BIEfU0EH3tFLMIebyU8V54eMMtjDLQ65LZB6PH+5X8s3F6yAPI70=(2) 前端代码const publicKey = ` -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsdYk9Dm8kSgtOsH/ljdb/S00MHevF9W/FOfmQIfUH+5u+x4kLS4Ncvdb9G+9A6/x0T+47hixU5yufjSTHIxjag3wxagkLQN3mptlAAW8B0u+qkRUG0oOUCgKbw3Hzmbalpm8MEgzJCORp2Cm0jtxGWQmAQV86ZWmykAinJhijowIDAQAB -----END PUBLIC KEY-----`;const signature = `JQ2FWaAbHWIkl4uSIxyMNbARFzSNKc7mOtXidm7hCRN85D8DVgZll02DYcWRSnn/ejOOxOrEPF8AcYHWx1repHh/jHcwv2focjF3Yne7NkQ4yGvgILDD2s1BIEfU0EH3tFLMIebyU8V54eMMtjDLQ65LZB6PH+5X8s3F6yAPI70=`;const message = `test`;const isVerified = CryptoUtils.verifyBySHA256WithRSA(publicKey, signature, message);console.log(`是否验签通过:${isVerified}`);

控制台输出如下:

是否验签通过:true

备注:因为我们在前端解析密钥时读取的是标准pem格式密钥,所以从后端复制过来的公钥一定要加上-----BEGIN PUBLIC KEY-----前缀和-----END PUBLIC KEY-----后缀,否则会报错。

本文链接地址:https://www.jiuchutong.com/zhishi/287057.html 转载请保留说明!

上一篇:最小的蓝牙鼠标是什么(最小的蓝牙鼠标是哪款)

下一篇:图像分割之U-Net、U2-Net及其Pytorch代码构建(图像分割 unet)

  • 苹果手机亮屏时间怎么调(苹果手机亮屏时闹钟不响)

    苹果手机亮屏时间怎么调(苹果手机亮屏时闹钟不响)

  • 华为荣耀8手机电池容量多少(华为荣耀8手机价格)

    华为荣耀8手机电池容量多少(华为荣耀8手机价格)

  • p站如何搜索视频(怎么在p站搜视频)

    p站如何搜索视频(怎么在p站搜视频)

  • iphonex快充多少w(iphonex快充用多少w的)

    iphonex快充多少w(iphonex快充用多少w的)

  • 拼多多评价多久会生效(拼多多评价多久过期)

    拼多多评价多久会生效(拼多多评价多久过期)

  • 闲鱼黑名单有什么用(闲鱼黑名单人数有上限吗)

    闲鱼黑名单有什么用(闲鱼黑名单人数有上限吗)

  • qq加入黑名单对方知道吗(qq加入黑名单对方信息是什么状态)

    qq加入黑名单对方知道吗(qq加入黑名单对方信息是什么状态)

  • iphone11屏幕失灵乱跳(iphone11屏幕失灵怎么强制关机)

    iphone11屏幕失灵乱跳(iphone11屏幕失灵怎么强制关机)

  • 华为nova7电池不耐用(华为nova7电池不耐用可以换吗)

    华为nova7电池不耐用(华为nova7电池不耐用可以换吗)

  • 抖音号必须用手机号注册吗(抖音号必须手机号么)

    抖音号必须用手机号注册吗(抖音号必须手机号么)

  • 淘宝介入处理时间一般是多久(淘宝介入处理时效多久)

    淘宝介入处理时间一般是多久(淘宝介入处理时效多久)

  • 手机不烫一直显示温度过高(手机不热但是出现温度过高怎么回事)

    手机不烫一直显示温度过高(手机不热但是出现温度过高怎么回事)

  • qq发了说说却显不出来(qq发了说说资料为什么有显示)

    qq发了说说却显不出来(qq发了说说资料为什么有显示)

  • 快手怎么看人在不在线(快手怎么看在不在线状态)

    快手怎么看人在不在线(快手怎么看在不在线状态)

  • 有边距打印和无边距打印的区别(有边距打印和无边距打印区别)

    有边距打印和无边距打印的区别(有边距打印和无边距打印区别)

  • 路由器隐藏了怎么连接(路由器隐藏了怎么恢复手机)

    路由器隐藏了怎么连接(路由器隐藏了怎么恢复手机)

  • 荣耀play3什么时候开售(荣耀play3什么时候升级鸿蒙)

    荣耀play3什么时候开售(荣耀play3什么时候升级鸿蒙)

  • 三星手机怎么下载微信(三星手机怎么下载音乐当铃声)

    三星手机怎么下载微信(三星手机怎么下载音乐当铃声)

  • 华为手机ar功能如何使用(手机ar功能在哪里)

    华为手机ar功能如何使用(手机ar功能在哪里)

  • 微信置顶对方知道吗(微信置顶以后发朋友会提示吗)

    微信置顶对方知道吗(微信置顶以后发朋友会提示吗)

  • 朋友圈怎么置顶第一条(朋友圈怎么置顶作品)

    朋友圈怎么置顶第一条(朋友圈怎么置顶作品)

  • 闪照怎么找回(qq闪照怎么找回)

    闪照怎么找回(qq闪照怎么找回)

  • 小米9支持双电信卡吗(小米支持双电信卡吗)

    小米9支持双电信卡吗(小米支持双电信卡吗)

  • Dedecms织梦系统Tag标签如何设置伪静态?(织梦cms官网)

    Dedecms织梦系统Tag标签如何设置伪静态?(织梦cms官网)

  • c语言中typedef关键字是什么(c语言中的typedef struct)

    c语言中typedef关键字是什么(c语言中的typedef struct)

  • 产权转移书据印花税政策
  • 免缴车船税
  • 车船税是什么意思图片
  • 非居民个人如何认定
  • 支付职工的培训费计入什么科目
  • 小规模纳税人开票税率
  • 个体户一定要自己经营吗
  • 与企业日常无关的政府补服属于利得吗
  • 收到税务局汇算清缴通知
  • 销项税的抵扣
  • 计提社保贷方科目是什么
  • 税费的计提和缴纳
  • 土地不动产登记证办理流程
  • 公司向股东借款计入什么科目
  • 材料采购成本差异属于什么科目
  • 增值税税收返还资料
  • 简易计征的税率
  • 税务与审计调整结果不一致该如何调整?
  • 工会开发票有税号吗?
  • 自行建造厂房一座,现已完工,经验收后交付费用
  • 公司注销增值税在借方有余额怎么处理
  • 对公账户的利息收入如何入账
  • 预付费服务是什么
  • 企业年金个税如何计提
  • 进口货物的关税税率
  • 认缴制下收到股东转入的钱怎么入账
  • 汇算清缴补交所得税后报表需要调整吗
  • mac怎么开机
  • 苹果手机14pro max
  • 上年度第四季度总结
  • 收到以前年度退税款的会计分录
  • 不起眼的暴利小生意农村
  • 澳大利亚太平洋银行
  • 制造企业成本计算模型有哪些类型
  • api接口是干嘛的
  • php中数组的概念
  • 现金折扣账务处理
  • php数据库网址
  • 查询公司对公账户
  • 个人综合所得汇算申报流程
  • linux服务器架设指南
  • 小微企业和民营企业的区别
  • 社保交费银行对账怎么办
  • 电子税务局怎么查询开票记录
  • 新办企业小规模纳税人多久可以申请发票增量
  • 财政补贴收入怎么做账
  • 低值易耗品如何界定
  • 个人所得税能说明什么
  • 应收账款属于会计分录
  • 可供出售金融资产公允价值变动
  • 现金解款单是什么
  • 什么是公允价值变动收益
  • 计提医疗保险费的会计分录
  • 收到员工社保
  • 报表的应付账款怎么算
  • 开办费账务处理实操案例
  • 应当设置会计机构的单位有
  • 会计备注一般写什么
  • linux下mysql5.7.17最新稳定版本安装教程
  • rdesktop命令
  • xp输入法图标消失
  • macbook屏幕自动亮度调节
  • 如何在linux
  • centos开启后一直黑屏
  • g++编译debug
  • windows7出现错误恢复怎么办
  • win7系统英雄联盟黑屏
  • win7浏览器怎么升级到最新版
  • perl字符串长度函数
  • window批处理
  • ftp下载怎么用
  • python的threading
  • cocos2djs
  • 接口回调java
  • javascript如何
  • vue中的event
  • jqgrid 动态表头
  • android root 原理
  • 13%增值税发票怎么抵扣
  • 如何落实请示汇报
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设