加密过程
1.1生成RSA密钥对
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
public class RSAKeyPairGenerator {
private KeyPair keyPair;
public RSAKeyPairGenerator() throws NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2048);
this.keyPair = keyGen.generateKeyPair();
}
public KeyPair getKeyPair() {
return keyPair;
}
}
2.加密AES密钥并发送给客户端
import javax.crypto.Cipher;
import java.security.PublicKey;
public class RSAEncrypt {
public byte[] encryptAESKey(byte[] aesKey, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(aesKey);
}
}
3.使用AES-GCM模式加密数据
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;
public class AESGCMEncrypt {
private static final int AES_KEY_SIZE = 256;
private static final int GCM_IV_LENGTH = 12;
private static final int GCM_TAG_LENGTH = 16;
public static SecretKey generateAESKey() throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(AES_KEY_SIZE);
return keyGen.generateKey();
}
public static byte[] encrypt(byte[] plaintext, SecretKey key, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
cipher.init(Cipher.ENCRYPT_MODE, key, gcmSpec);
return cipher.doFinal(plaintext);
}
public static byte[] generateIV() {
byte[] iv = new byte[GCM_IV_LENGTH];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
return iv;
}
}
4.服务端逻辑整合
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.SecretKey;
public class Server {
public static void main(String[] args) {
try {
// 生成RSA密钥对
RSAKeyPairGenerator rsaKeyPairGenerator = new RSAKeyPairGenerator();
KeyPair keyPair = rsaKeyPairGenerator.getKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 生成AES密钥
SecretKey aesKey = AESGCMEncrypt.generateAESKey();
// 加密AES密钥
RSAEncrypt rsaEncrypt = new RSAEncrypt();
byte[] encryptedAESKey = rsaEncrypt.encryptAESKey(aesKey.getEncoded(), publicKey);
// 生成IV
byte[] iv = AESGCMEncrypt.generateIV();
// 加密数据(示例数据)
String plaintext = "This is a secret message.";
byte[] encryptedData = AESGCMEncrypt.encrypt(plaintext.getBytes(), aesKey, iv);
// 输出加密结果
System.out.println("Encrypted AES Key: " + Base64.getEncoder().encodeToString(encryptedAESKey));
System.out.println("IV: " + Base64.getEncoder().encodeToString(iv));
System.out.println("Encrypted Data: " + Base64.getEncoder().encodeToString(encryptedData));
// 这里可以将加密的AES密钥、IV和加密的数据发送给客户端
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.解密过程
1.RSA解密AES密钥
import javax.crypto.Cipher;
import java.security.PrivateKey;
public class RSADecrypt {
public byte[] decryptAESKey(byte[] encryptedAESKey, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(encryptedAESKey);
}
}
2.使用AES-GCM解密数据
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESGCMDecrypt {
private static final int GCM_TAG_LENGTH = 16;
public static byte[] decrypt(byte[] ciphertext, SecretKey key, byte[] iv) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);
cipher.init(Cipher.DECRYPT_MODE, key, gcmSpec);
return cipher.doFinal(ciphertext);
}
}
2.服务端解密逻辑整合
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class ServerDecrypt {
public static void main(String[] args) {
try {
// 生成RSA密钥对(在实际应用中,这应该是从安全存储中加载的)
RSAKeyPairGenerator rsaKeyPairGenerator = new RSAKeyPairGenerator();
KeyPair keyPair = rsaKeyPairGenerator.getKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
// 假设这些数据是从客户端接收到的
String encryptedAESKeyBase64 = "接收到的加密AES密钥的Base64字符串";
String ivBase64 = "接收到的IV的Base64字符串";
String encryptedDataBase64 = "接收到的加密数据的Base64字符串";
// 将Base64字符串转换为字节数组
byte[] encryptedAESKey = Base64.getDecoder().decode(encryptedAESKeyBase64);
byte[] iv = Base64.getDecoder().decode(ivBase64);
byte[] encryptedData = Base64.getDecoder().decode(encryptedDataBase64);
// 解密AES密钥
RSADecrypt rsaDecrypt = new RSADecrypt();
byte[] aesKeyBytes = rsaDecrypt.decryptAESKey(encryptedAESKey, privateKey);
SecretKey aesKey = new SecretKeySpec(aesKeyBytes, 0, aesKeyBytes.length, "AES");
// 解密数据
byte[] decryptedData = AESGCMDecrypt.decrypt(encryptedData, aesKey, iv);
// 输出解密结果
String plaintext = new String(decryptedData);
System.out.println("Decrypted Data: " + plaintext);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意事项:
1.选择合适的密钥长度:RSA和AES的密钥长度对安全性有很大影响。一般来说,RSA密钥长度建议选择2048位或更高,AES密钥长度建议选择128位、192位或256位。
2.iv长度一般是96位12个(字节);tag长度为128位(16个字节)
3.Cipher包生成的密文是带有tag的,而且也会校验tag;那也就意味着客户端传的密文也要带上tag,一般拼接在密文后