一、AES与RSA联合加密
1. 应用步骤:
- AES(对称加密)与RSA(非对称加密)联合使用示例及步骤(A请求B的某个页面):
- A端生成AES密钥
- B端生成RSA公钥(用于加密)和私钥(用于解密),并将公钥给A
- A使用自己的AES密钥对自己的私密信息进行加密,并使用B提供的公钥对AES密钥进行加密,然后将请求信息和加密后的AES密钥发送给B
- B使用RSA私钥对加密的AES密钥进行解密,然后用AES密钥对A的请求信息进行解密
- B验证A的请求信息,实现后续的操作。
2. 理论基础
- 为什么联合使用AES与RSA加密算法
- AES是对称加密算法,在传输过程中容易被窃取,但加密效率高
- RSA是非对称加密算法,安全性高,但加密效率低
- RSA公钥加密的内容,只有对应的私钥才能解密,对于较长的内容,可以选择使用AES加密,然后用公钥加密AES密钥的方式进行加密。
二、代码实现秘钥生成以及加密解密操作
1. C# 实现
1.1 AES生成密钥、AES加解密操作
public class AESUtil
{
//生成AES密钥
public static Aes GenerateAES()
{
Aes aes=Aes.Create();
return aes;
}
//获取AES密钥
public static byte[] GetAESKey(Aes aes)
{
byte[] key = aes.Key;
return key;
}
//使用AES加密数据
public static string AESEncript(string data, byte[] aesKey)
{
using (Aes aes = Aes.Create())
{
aes.Key = aesKey;
aes.IV = new byte[16];
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key,aes.IV);
using (MemoryStream ms=new MemoryStream())
{
using (CryptoStream cs=new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw=new StreamWriter(cs))
{
sw.Write(data);
}
}
return Convert.ToBase64String(ms.ToArray());
}
}
}
//使用AES解密数据
public static string AESDecript(string data,byte[] aesKey)
{
using (Aes aes = Aes.Create())
{
aes.Key = aesKey;
aes.IV=new byte[16];
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key,aes.IV);
using (MemoryStream ms =new MemoryStream(Convert.FromBase64String(data)))
{
using (CryptoStream cs=new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
{
using (StreamReader sr=new StreamReader(cs))
{
return sr.ReadToEnd();
}
}
}
}
}
}
1.2 RSA密钥生成、RSA加解密
public class RSAUtil
{
//生成RSA密钥对
public static RSA GenerateRSA()
{
RSA rsa=RSA.Create(2048);
return rsa;
}
//获取公钥
public static byte[] GetRSAPublicKey(RSA rsa)
{
var publicKey = rsa.ExportRSAPublicKey(); //导出当前密钥的公钥部分
return publicKey;
}
//获取私钥
public static byte[] GetRSAPrivateKey(RSA rsaKeyPair)
{
var privateKey = rsaKeyPair.ExportRSAPrivateKey();//导出当前密钥的私钥部分
return privateKey;
}
//公钥加密
public static byte[] RSAEncrypt(byte[] data,byte[] publicKey)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportRSAPublicKey(publicKey,out int bytesRead);//导入公钥,从 PKCS#1 RSAPublicKey 结构中导入公钥
return rsa.Encrypt(data,RSAEncryptionPadding.Pkcs1);//加密,RSAEncryptionPadding.Pkcs1:加密标准
}
}
//私钥解密
public static byte[] RSADecrypt(byte[] data, byte[] privateKey)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportRSAPrivateKey(privateKey,out int bytesRead);
return rsa.Decrypt(data, RSAEncryptionPadding.Pkcs1);
}
}
}
扩展:从.pem文件中读取秘钥进行信息加密:
public string GetRSAToEncrypt()
{
string file_path = "D:/public_key.pem";
using (StreamReader reader = new StreamReader(file_path))
{
var pem = reader.BaseStream;
byte[] buffer = new byte[pem.Length];
pem.Read(buffer, 0, buffer.Length);
var content = Encoding.UTF8.GetBytes("aaa");
string result = "";
using (RSA rsa = RSA.Create())
{
rsa.ImportSubjectPublicKeyInfo(buffer, out int bt);
var en = rsa.Encrypt(content, RSAEncryptionPadding.Pkcs1);
result = Convert.ToBase64String(en);
}
return result;
}
}
1.3 AES与RSA联合使用实现加解密步骤:
//生成AES密钥
Aes aes = AESUtil.GenerateAES();
byte[] aesKey = AESUtil.GetAESKey(aes);
//用AES密钥对信息加密
string enCryptInfo = AESUtil.AESEncript(userInfo, aesKey);
//用公钥对AES密钥加密(若是对string类型加密,加密前要先Encoding.UTF8.GetBytes(content))
byte[] enCryptAESByRSA = RSAUtil.RSAEncrypt(aesKey, rsaPublicKey);
//用私钥对加密的AES解密
byte[] deCryptAESByRSA = RSAUtil.RSADecrypt(enCryptAESByRSA, rsaPrivateKey);
//用AES对加密信息解密
string deCryptInfo = AESUtil.AESDecript(enCryptInfo, deCryptAESByRSA);
2. Java实现
2.0 添加依赖
<!-- hutool 工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
2.1 RSA秘钥对生成
生成RSA秘钥对,并将生成的秘钥保存为.pem文件
import cn.hutool.crypto.asymmetric.RSA;
@Service
public class RsaUtils {
public Object getRsaKeys()
{
//生成秘钥对
RSA rsa=new RSA();
String publicKey=rsa.getPublicKeyBase64();
String privateKey=rsa.getPrivateKeyBase64();
Map<String,String> rsaKeys= new HashMap<String,String>();
rsaKeys.put("public_key",publicKey);
rsaKeys.put("private_key",privateKey);
//转换为pem文件的保存格式
String publicKey_pem=formatKeyToPem("PUBLIC KEY",publicKey);
String privateKey_pem=formatKeyToPem("PRIVATE KEY",privateKey);
//保存为pem文件
String path= Paths.get("").toAbsolutePath()+"/Files/Keys/";
try(PrintWriter pw=new PrintWriter(new FileWriter(path+"rsa_pubilcKey.pem")))
{
pw.println(publicKey_pem);
} catch (IOException e) {
e.printStackTrace();
}
try(PrintWriter pw=new PrintWriter(new FileWriter(path+"rsa_privateKey.pem")))
{
pw.println(privateKey_pem);
} catch (IOException e) {
e.printStackTrace();
}
return rsaKeys;
}
private String formatKeyToPem(String keyType,String base64Key)
{
final int line_length=64;
StringBuilder stringBuilder=new StringBuilder();
stringBuilder.append("-----BEGIN ")
.append(keyType)
.append("-----\n");
for(int i=0;i<base64Key.length();i+=line_length)
{
int endIndex=Math.min(i+line_length,base64Key.length());
stringBuilder.append(base64Key,i,endIndex).append("\n");
}
stringBuilder.append("-----END ")
.append(keyType)
.append("-----\n");
return stringBuilder.toString();
}
}
2.2 RSA加密与解密
//加密
public String RsaEncrypt(String data)
{
try{
//获取公钥
String public_key=getRsaKey("rsa_pubilcKey.pem");
//创建RSA实例,使用公钥进行加密
RSA rsa=new RSA(null,public_key);
byte[] dataEncrypted=rsa.encrypt(data.getBytes(StandardCharsets.UTF_8), KeyType.PublicKey);
//加密内容格式化
String dataBase64= Base64Encoder.encode(dataEncrypted);//转化为Base64编码
String dateUrlEncode=URLEncoder.encode(dataBase64,"UTF-8");//将字符串处理成适合在url中传输的格式
return dateUrlEncode;
}
catch (Exception ex)
{
return ex.getMessage();
}
}
//解密
public String RsaDecrypt(String encryptedData)
{
try{
//获取私钥
String privateKey=getRsaKey("rsa_privateKey.pem");
//加密信息处理
String base64Data= URLDecoder.decode(encryptedData,"UTF-8");
byte[] byteData= Base64Decoder.decode(base64Data);
//创建RSA实例,使用RSA私钥进行解密
RSA rsa=new RSA(privateKey,null);
byte[] decryptedData=rsa.decrypt(byteData,KeyType.PrivateKey);
String result=new String(decryptedData);
return result;
}
catch (Exception ex)
{
return ex.getMessage();
}
}
//获取秘钥
private String getRsaKey(String fileName)
{
String path=Paths.get("").toAbsolutePath()+"/Files/Keys/"+fileName;
try{
String rsaKey=new String(Files.readAllBytes(Paths.get(path)));
rsaKey=rsaKey.replace("-----BEGIN PRIVATE KEY-----","")
.replace("-----END PRIVATE KEY-----","")
.replace("-----BEGIN PUBLIC KEY-----","")
.replace("-----END PUBLIC KEY-----","")
.replaceAll("\\s+","");//取出所有的空格、回车、tab键
return rsaKey;
}
catch (Exception ex)
{
return ex.getMessage();
}
}
2.3 AES秘钥生成
2.3.0 所用依赖
两种用于AES加密的依赖:
KeyGenerator:
- 允许自定义密钥长度(128、192、256位等)。
- 适用于标准的Java加密架构。
- 提供更细致的控制,适合需要特定配置的场景。
- 只适用于对称加密算法,如AES、DES等。
Hutool的AES类:
- 更简洁,快速生成AES密钥,适合快速开发。
- 默认生成密钥,配置较少。
- 适合日常使用,不需要过多配置
2.3.1 使用Hutool的AES类生成秘钥
import cn.hutool.crypto.symmetric.AES;
@Service
public class AESUtils {
public String getAesKey()
{
AES aes=new AES();
byte[] aesKey=aes.getSecretKey().getEncoded();
String key= Base64Encoder.encode(aesKey);
String path= Paths.get("").toAbsolutePath()+"/Files/Keys/aes_key.txt";
try(PrintWriter pw=new PrintWriter(new FileWriter(path)))
{
pw.println(key);
} catch (IOException e) {
e.printStackTrace();
}
return key;
}
}
2.3.2 使用KeyGenerator生成秘钥
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public String getFixedLengthAesKey(int length)
{
try {
//创建KeyGenerator对象,指定AES算法
KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
//初始化秘钥大小,常见128,192,256
keyGenerator.init(length);
//生成AES秘钥
SecretKey secretKey=keyGenerator.generateKey();
byte[] keyByte=secretKey.getEncoded();
String keyBase64=Base64Encoder.encode(keyByte);
return keyBase64;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
未完待续
本文介绍如何结合使用AES和RSA加密算法来提高信息安全。通过AES加密大量数据并利用RSA加密AES密钥,确保了数据传输的安全性和高效性。
4245

被折叠的 条评论
为什么被折叠?



