AES和RSA混搭风格
===========
为什么要使用AESxRSA混搭风格
首先我们必须要了解常见的加密算法有哪些特点,并选择合适的解决方案来满足我们的安全需求,本文内容着重探讨的是AESxRSA组合加密的实现方案。
常见加密算法
本次重点介绍AES和RSA加密算法的混搭方式是如何实现高效、安全、快捷的加密方式以满足业务的需求。
如果对常见密码算法做一个分类,那么结构图大概如下所示:
什么是 AES 加密 和 RSA 加密?
AES(Advanced Encryption Standard,高级加密标准)
AES 是一种对称加密算法,即加密和解密使用相同的密钥。AES 的密钥长度可以选择 128 位、192 位或 256 位。AES 的加密过程包括多轮的重复操作,包括置换、替换、行移位和列混合等。AES算法具有较高的安全性和运算效率,广泛应用于保护数据的机密性。
RSA(由发明者Rivest、Shamir、Adleman的姓氏首字母组成)
RSA 是一种非对称加密算法,即加密和解密使用一对不同的密钥,分别称为公钥和私钥。公钥用于加密数据,私钥用于解密数据。RSA 算法的安全性基于大数分解问题,密钥长度通常选择 1024 位、2048 位或更长。RSA 算法用于保护数据的机密性、确保数据的完整性和实现数字签名等功能。
AES 加密 和 RSA 加密的区别是什么?
对称加密与非对称加密:AES 是对称加密算法,加密和解密使用相同的密钥;而RSA 是非对称加密算法,加密和解密使用不同的密钥。
效率方面:AES 加密和解密的运算速度较快,消耗资源较少;而 RSA 算法由于涉及大数计算,运算速度较慢,消耗资源较多。
应用场景:AES 适用于加密大量数据,如文件加密、网络通信加密等;RSA 常用于加密较小的数据,如密钥交换、数字签名等,。
加密方式比较:
- 针对名称:采用
单加密
的方法,同一个密码可以同时用来解密 。常见的针对名称算法有DES
,3DES
等AES
。 - 非针对性加密,需要
两个秘钥
进行加密和解密,这两个密钥是公开密钥(public key,简称公钥) 和私有密钥(private key,简称私钥) 。常见的非针对性加密算法有RSA
,Elgamal
等ECC
。
| 名称 | RSA | AES |
| — | — | — |
| 加密方式 | 非对称 | 对称 |
| 秘钥的使用 | 不同的密钥用于加密和解密数据 | 同一个密钥用于加密和解密数据 |
| 最小长度 | 512 位 | 128 位 |
| 秘钥长度 | 512 位, 1024 位,2048 位或更长 | 10–128 位, 12–192 位, 14–256 位 |
| 安全性 | 较高 | 一般 |
| 效率 | 慢 | 快 |
AESxRSA加解密流程
- 发送方首先通过AES算法生成AES秘钥。
- 发送方通过AES秘钥对原始的数据内容进行加密后产生密文。
- 发送方通过RSA的私有秘钥对AES秘钥进行加密得到加密后的秘钥。
- 发送方将加密后的密文和密钥发送给接收方。
- 接收方通过RSA公钥对加密后的秘钥进行解密得到AES的秘钥。
- 接收方通过ESA秘钥解密加密后的密文数据。
AESxRSA Java实现代码
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAAndAESCombination {
// RSA密钥长度
private static final int RSA_KEY_SIZE = 2048;
// AES密钥长度
private static final int AES_KEY_SIZE = 128;
// 用于AES加密的密钥别名
private static final String AES_KEY_ALIAS = "aesKey";
// RSA密钥生成
public static KeyPair generateRSAKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(RSA_KEY_SIZE);
return keyPairGenerator.generateKeyPair();
}
// AES密钥生成
public static SecretKey generateAESKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(AES_KEY_SIZE);
return keyGenerator.generateKey();
}
// 使用RSA公钥加密AES密钥
public static String encryptAESKeyWithRSA(SecretKey aesKey, PublicKey rsaPublicKey) throws Exception {
Cipher rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);
byte[] encryptedAesKey = rsaCipher.doFinal(aesKey.getEncoded());
return Base64.getEncoder().encodeToString(encryptedAesKey);
}
// 使用AES密钥加密数据
public static String encryptDataWithAES(String data, SecretKey aesKey) throws Exception {
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 注意:ECB模式仅用于示例,通常建议使用CBC或其他模式
aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encryptedData = aesCipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedData);
}
// 使用RSA私钥解密AES密钥
public static SecretKey decryptAESKeyWithRSA(String encryptedAesKey, PrivateKey rsaPrivateKey) throws Exception {
byte[] decodedAesKey = Base64.getDecoder().decode(encryptedAesKey);
Cipher rsaCipher = Cipher.getInstance("RSA");
rsaCipher.init(Cipher.DECRYPT_MODE, rsaPrivateKey);
byte[] decryptedAesKey = rsaCipher.doFinal(decodedAesKey);
return new SecretKeySpec(decryptedAesKey, "AES");
}
// 使用AES密钥解密数据
public static String decryptDataWithAES(String encryptedData, SecretKey aesKey) throws Exception {
byte[] decodedData = Base64.getDecoder().decode(encryptedData);
Cipher aesCipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 注意:ECB模式仅用于示例,通常建议使用CBC或其他模式
aesCipher.init(Cipher.DECRYPT_MODE, aesKey);
byte[] decryptedData = aesCipher.doFinal(decodedData);
return new String(decryptedData, StandardCharsets.UTF_8);
}
// 主函数,用于测试
public static void main(String[] args) throws Exception {
// 生成RSA密钥对
KeyPair rsaKeyPair = generateRSAKeyPair();
PublicKey rsaPublicKey = rsaKeyPair.getPublic();
PrivateKey rsaPrivateKey = rsaKeyPair.getPrivate();
// 生成AES密钥
SecretKey aesKey = generateAESKey();
// 将密钥转换为字节数组
byte[] encoded = aesKey.getEncoded();
// 通常,密钥不会直接以字节形式存储或传输,而是会进行Base64编码
String base64EncodedKey = Base64.getEncoder().encodeToString(encoded);
System.out.println("AES Key: " + base64EncodedKey);
// 待加密的数据
String originalData = "Hello, RSA and AES Encryption!";
System.out.println("原始数据: " + originalData);
// 使用RSA公钥加密AES密钥
String encryptedAesKey = encryptAESKeyWithRSA(aesKey, rsaPublicKey);
System.out.println("RSA私钥加密 AES Key: " + encryptedAesKey);
// 使用AES密钥加密数据
String encryptedData = encryptDataWithAES(originalData, aesKey);
System.out.println("AES加密后的数据: " + encryptedData);
// 使用RSA公钥解密
SecretKey secretKey = decryptAESKeyWithRSA(encryptedAesKey, rsaPrivateKey);
// 将密钥转换为字节数组
byte[] encodeds = secretKey.getEncoded();
// 通常,密钥不会直接以字节形式存储或传输,而是会进行Base64编码
String base64EncodedKeys = Base64.getEncoder().encodeToString(encoded);
// 打印Base64编码的密钥
System.out.println("RSA私钥加密 AES Key: " + base64EncodedKey);
//AES解密后的数据
String decryptedData = decryptDataWithAES(encryptedData, secretKey);
System.out.println("AES解密后的数据: " + decryptedData);
}
}
代码执行结果
AES Key: sMKUkf/sJD6S4lB/rrA0Dw==
原始数据: Hello, RSA and AES Encryption!
RSA私钥加密 AES Key: CYhFrJ7p2yzr07fkYj7F0hmX4SNDbHjfrFBW8jjFnhbqFba0N0X0Q2NVhBraLC6M36jQoAWDQwoYVhK6/b1+H+pElP+HTKhj2KLi5oCddP57+6VYRKF13WW5mNWYejA7M0ieujqhoXJzfo77KJdsZmHGl3lBfVh3bHyzTW3jjWPEN4rm/fJ7b+NaaruuphMgWUgKJLJsj+TPXkkhwg6U0hJ2ahxiTbjcvlWHP+f6MYy0KdSTB1Osc5RqedMUoHHLob6osXsL/Q6nwKYyJsop0PvXtH1zfNx03wsDHXWAceolBGlSwcLT2d4Z1VsAfHgd9fMJNIRGGl61WiGs+3TAsw==
AES加密后的数据: ozoaVuXVGnGzREXEYF1xqXMEsJbzUIdTC/4JygTNJe8=
RSA私钥加密 AES Key: sMKUkf/sJD6S4lB/rrA0Dw==
AES解密后的数据: Hello, RSA and AES Encryption!
原文链接: https://juejin.cn/post/7383879646327308300
文章收集整理于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除,如若转载,请注明出处:http://www.cxyroad.com/17150.html