赞
踩
RSA是非对称加密的一种,具有两个密钥:公共密钥和私有密钥。公钥和私钥是一对,公钥加密后的内容只有私钥才能解密。两个密钥的不同,所以是非对称的。
AES是对称加密的一种,加密和解密的密钥都是一个。
由此就可以看出两者的优势和劣势:
RSA相对安全,但是加密速度则会慢;而AES加密速度快,但是安全性相对差。
下面直接用登录功能的前后端交互图作为案例:
而后就是对应的工具库的问题,有很多可以实现加密的工具。但是前后端需要能用一样的加密和解密的算法才行。
RSA/ECB/PKCS1Padding,这个是RSA算法的具体实现方式,这个有很多种,比如还有ECB因此很容易和别人的算法不匹配。
这里看了别人的文章补充一下:
后端代码:
import java.security.*; import java.security.spec.PKCS8EncodedKeySpec; import javax.crypto.Cipher; import java.util.Base64; public class RSADecrypt { public static String decrypt(String encryptedText, String privateKey) throws Exception { byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText); byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey key = keyFactory.generatePrivate(keySpec); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return new String(decryptedBytes); } public static void main(String[] args) throws Exception { // 生成RSA密钥对 // 使用自定义的种子值来初始化 KeyPairGenerator byte[] seed = "RSA".getBytes(); // 用自己想要的值替换这里的固定种子值 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048, new SecureRandom(seed)); KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); // 将公钥和私钥转换成Base64编码的字符串,以便传递给前端和后端 String publicKeyString = Base64.getEncoder().encodeToString(publicKey.getEncoded()); String privateKeyString = Base64.getEncoder().encodeToString(privateKey.getEncoded()); }
“jsencrypt”: “^3.3.2”
import JsEncrypt from 'jsencrypt'
var encrypt = new JsEncrypt();
encrypt.setPublicKey();
this.encryptedAesKey = encrypt.encrypt()
AES/ECB/PKCS5Padding 注意算法方式
import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import javax.crypto.*; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; /** * AES对称加密工具类 */ public class AESUtil { /** * 加密算法 */ private static String Algorithm = "AES"; /** * 算法/模式/补码方式 */ private static String AlgorithmProvider = "AES/ECB/PKCS5Padding"; /** * 加密 * * @param src 原内容 * @param uniqueKey 唯一key * @return * @throws NoSuchPaddingException * @throws NoSuchAlgorithmException * @throws InvalidKeyException * @throws BadPaddingException * @throws IllegalBlockSizeException * @throws DecoderException */ public static String encrypt(String src, String uniqueKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, DecoderException { byte[] key = uniqueKey.getBytes(); SecretKey secretKey = new SecretKeySpec(key, Algorithm); Cipher cipher = Cipher.getInstance(AlgorithmProvider); cipher.init(Cipher.ENCRYPT_MODE, secretKey); byte[] cipherBytes = cipher.doFinal(src.getBytes(StandardCharsets.UTF_8)); return byteToHexString(cipherBytes); } /** * 解密 * * @param enc 加密内容 * @param uniqueKey 唯一key * @return * @throws NoSuchPaddingException * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException * @throws InvalidAlgorithmParameterException * @throws InvalidKeyException * @throws DecoderException * @throws BadPaddingException * @throws IllegalBlockSizeException */ public static String decrypt(String enc, String uniqueKey) throws NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidAlgorithmParameterException, InvalidKeyException, DecoderException, BadPaddingException, IllegalBlockSizeException { byte[] key = uniqueKey.getBytes(); SecretKey secretKey = new SecretKeySpec(key, Algorithm); Cipher cipher = Cipher.getInstance(AlgorithmProvider); cipher.init(Cipher.DECRYPT_MODE, secretKey); byte[] hexBytes = hexStringToBytes(enc); byte[] plainBytes = cipher.doFinal(hexBytes); return new String(plainBytes, "UTF-8").replaceAll("^\"|\"$", ""); } /** * 将byte数组转换为16进制字符串 * * @param src * @return */ private static String byteToHexString(byte[] src) { return Hex.encodeHexString(src); } /** * 将16进制字符串转换为byte数组 * * @param hexString * @return */ private static byte[] hexStringToBytes(String hexString) throws DecoderException { return Hex.decodeHex(hexString); } }
AES前端代码:
//生成指定长度随机字符串
generateRandomStr(strLength = 16) {
let code = '';
const chars = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
const charsArr = chars.split('');
for (let i = 0; i < strLength; i++) {
const num = Math.floor(Math.random() * charsArr.length);
code += charsArr[num];
}
return code;
},
const encryptedContent_zh = CryptoJS.AES.encrypt(content_zh, this.key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }); const encStr_zh = encryptedContent_zh.ciphertext.toString(); this.encStr_zh = encryptedContent_zh.ciphertext.toString(); const encryptedContent_mm = CryptoJS.AES.encrypt(content_mm, this.key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }); // 解密方法 const decryptedContent_zh = CryptoJS.AES.decrypt( CryptoJS.format.Hex.parse(encStr_zh), this.key,//注意:后面这里最好使用 CryptoJS.format.Utf8.parse(key) { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 } );
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。