AES加密 + RSA签名
public class Main {
public static void main(String[] args) throws Exception {
// 生成RSA密钥对
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
KeyPair keyPair = keyGen.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 将公钥和私钥转换为Base64编码的字符串
String rsaPublicKeyStr = Base64.getEncoder().encodeToString(publicKey.getEncoded());
String rsaPrivateKeyStr = Base64.getEncoder().encodeToString(privateKey.getEncoded());
// 对称加密算法
String algorithm = "AES";
// AES密钥(长度通常为128、192或256位)
KeyGenerator aesKeyFactor = KeyGenerator.getInstance(algorithm);
aesKeyFactor.init(128); // 128-bit AES key
byte[] aesKey = aesKeyFactor.generateKey().getEncoded();
// String key = "1234567812345678"; // 16字节*8 = 128位
// 敏感信息
String content = "{\"dog_name\":\"小.王\",\"dogGender\":\"male\"}";
String timestamp = String.valueOf(System.currentTimeMillis());
// 拼接时间戳
content = timestamp + "|" + content;
System.out.println("\n-----------发送方-----------\n");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(aesKey, algorithm);
// 随机初始化向量iv,以实现相同content加密后的密文是不同的
byte[] iv = new byte[12];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
String ivStr = Base64.getEncoder().encodeToString(iv);
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
// 加密模式
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
byte[] encryptBytes = cipher.doFinal(content.getBytes());
String encryptText = Base64.getEncoder().encodeToString(encryptBytes);
// RSA私钥签名
PrivateKey rsaPrivateKey = recoverPrivateKey(rsaPrivateKeyStr);
Signature signer = Signature.getInstance("SHA256withRSA");
signer.initSign(rsaPrivateKey);
// 获取SHA-256 MessageDigest实例
MessageDigest digest = MessageDigest.getInstance("SHA-256");
// 对密文进行哈希处理
byte[] hashBytes = digest.digest(encryptText.getBytes());
signer.update(hashBytes); // 对密文的哈希值进行签名(而非对密文本身签名),以此避免得到过长的签名结果
byte[] signatureBytes = signer.sign();
String signature = Base64.getEncoder().encodeToString(signatureBytes);
// 输出结果
System.out.println("Encrypted Text: " + encryptText);
System.out.println("Signature: " + signature);
System.out.println("ivStr: " + ivStr);
System.out.println("\n-----------接收方-----------\n");
// 验签
PublicKey rsaPublicKey = recoverPublicKey(rsaPublicKeyStr);
Signature verifier = Signature.getInstance("SHA256withRSA");
verifier.initVerify(rsaPublicKey);
verifier.update(hashBytes);
boolean isCorrect = verifier.verify(Base64.getDecoder().decode(signature));
if (isCorrect) {
System.out.println("验签成功");
} else {
System.out.println("验签失败");
}
// 解密
Cipher recieverCipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec receiverSk = new SecretKeySpec(aesKey, algorithm);
byte[] receiverIv = Base64.getDecoder().decode(ivStr);
GCMParameterSpec gcm = new GCMParameterSpec(128, receiverIv);
// 解密模式
recieverCipher.init(Cipher.DECRYPT_MODE, receiverSk, gcm);
// 先将加密后的字符串解码回字节数据
byte[] decodedBytes = Base64.getDecoder().decode(encryptText);
byte[] plainBytes = recieverCipher.doFinal(decodedBytes);
String plainText = new String(plainBytes).split("\\|")[1]; // 原文
System.out.println(plainText);
}
private static PublicKey recoverPublicKey(String key) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePublic(keySpec);
}
private static PrivateKey recoverPrivateKey(String key) throws Exception {
byte[] keyBytes = Base64.getDecoder().decode(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(keySpec);
}
}
AES加密+RSA签名的方案结合了AES的高加密速度和RSA的签名验证能力,适用于需要同时保证数据传输的机密性、完整性和来源可靠性的场景。例如,在网络通信中,可以使用AES加密数据内容,使用RSA签名来验证数据的完整性和来源。
结合了AES和RSA的优点,既保证了数据传输的速度和效率,又确保了数据的安全性和可靠性。