# 前言 在我们平时项目开发过程中,经常会遇到各种各样的数据安全问题,为了防止我们的业务数据不被泄露,提高我们系统的安全性。在数据传输的时候我们对传输的数据进行加密,这里采用了 RSA (非对称) + AES (对称加密)的方式。
- RSA:非对称加密,公钥(Public Key)与私钥(Private Key)是通过一种算法得到的一个密钥对(即一个公钥和一个私钥),公钥是密钥对中公开的部分,私钥则是非公开的部分。公钥通常用于加密会话密钥、验证数字签名,或加密可以用相应的私钥解密的数据。
- AES:对称加密,对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。
- 客户端启动,发送请求到服务端,服务端用 RSA 算法生成一对公钥和私钥,我们简称为publickey1,privatekey2,将公钥 publickey1 返回给客户端。
- 客户端拿到服务端返回的公钥 publickey1 后,自己用 RSA 算法生成一对公钥和私钥,我们简称为publickey2,privatekey2,并将公钥 publickey2通过公钥 publickey1加密,加密之后传输给服务端。
- 此时服务端收到客户端传输的密文,用私钥 privatekey1 进行解密,因为数据是用公钥 publickey1 加密的,通过解密就可以得到客户端生成的公钥 publickey2 。
- 然后自己在生成对称加密,也就是我们的 AES,其实也就是相对于我们配置中的那个 16 的长度的加密 key,生成了这个 key 之后我们就用公钥 publickey2 进行加密,返回给客户端,因为只有客户端有publickey2 对应的私钥 privatekey2,只有客户端才能解密。
- 客户端得到数据之后,用 privatekey2 进行解密操作,得到 AES 的加密 key,最后就用加密 key 进行数据传输的加密,至此整个流程结束。
public static void main(String[] args) throws Exception {
//获取 AES 的 key
String key = getKey();
String encrypt = encrypt("你们好啊",key);
System.out.println("加密之后"+key);
System.out.println("***********************");
String decrypt = decrypt(encrypt,key);
System.out.println("解密之后"+decrypt);
}
RSA 工具类 RSAUtil
//日志
private static final Logger logger = LoggerFactory.getLogger(RSAUtil.class);
static{
try{
Security.addProvider(new BouncyCastleProvider());
}catch(Exception e){
e.printStackTrace();
}
}
private static final String KEY_ALGORITHM = "RSA";
private static final String ALGORITHMS = "RSA/ECB/PKCS1Padding";
private static final int MAX_ENCRYPT_BLOCK = 245;
private static final int MAX_DECRYPT_BLOCK = 256;
private static final int INITIALIZE_LENGTH = 2048;
private static Map map = new LinkedHashMap<>(2);
public static Map genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(INITIALIZE_LENGTH);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 获取公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
// 获取私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥字符串
String publicKeyString = Base64.encodeBase64String(publicKey.getEncoded());
// 得到私钥字符串
String privateKeyString = Base64.encodeBase64String((privateKey.getEncoded()));
map.put("publicKey",publicKeyString);
map.put("privateKey",privateKeyString);
return map;
}
public static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception {
//base64格式的key字符串转Key对象
Key privateK = KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
Cipher cipher = Cipher.getInstance(ALGORITHMS);
cipher.init(Cipher.DECRYPT_MODE, privateK);
//分段进行解密操作
return encryptAndDecryptOfSubsection(data, cipher, MAX_DECRYPT_BLOCK);
}
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
//base64格式的key字符串转Key对象
Key publicK = KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(publicKey)));
Cipher cipher = Cipher.getInstance(ALGORITHMS);
cipher.init(Cipher.ENCRYPT_MODE, publicK);
//分段进行加密操作
return encryptAndDecryptOfSubsection(data, cipher, MAX_ENCRYPT_BLOCK);
}
public static byte[] pubKeyDec(byte[] data, String publicKey) throws Exception {
//base64格式的key字符串转Key对象
Key privateK = KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(publicKey)));
Cipher cipher = Cipher.getInstance(ALGORITHMS);
cipher.init(Cipher.DECRYPT_MODE, privateK);
//分段进行解密操作
return encryptAndDecryptOfSubsection(data, cipher, MAX_DECRYPT_BLOCK);
}
public static byte[] privKeyEnc(byte[] data, String privateKey) throws Exception {
//base64格式的key字符串转Key对象
Key publicK = KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
Cipher cipher = Cipher.getInstance(ALGORITHMS);
cipher.init(Cipher.ENCRYPT_MODE, publicK);
//分段进行加密操作
return encryptAndDecryptOfSubsection(data, cipher, MAX_ENCRYPT_BLOCK);
}
private static byte[] encryptAndDecryptOfSubsection(byte[] data, Cipher cipher, int encryptBlock) throws Exception {
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > encryptBlock) {
cache = cipher.doFinal(data, offSet, encryptBlock);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * encryptBlock;
}
out.close();
return out.toByteArray();
}
RSA + AES 测试类
//随机获取AES的key,加密data数据
String key = AESUtil.getKey();
//生成公钥和私钥
genKeyPair();
//获取公钥和私钥
String publicKey = map.get("publicKey");
String privateKey = map.get("privateKey");
System.out.println("=====================公钥加密,私钥解密==================");
//随机AES的key加密后的密文
String data = AESUtil.encrypt("你们好啊", key);
System.out.println("AES 加密之后:");
System.out.println(data);
//用公钥来加密AES的key,并转成Base64
String aesKey = Base64.encodeBase64String(encryptByPublicKey(data.getBytes(),publicKey));
System.out.println("RSA 加密之后:");
System.out.println(aesKey);
//用私钥解密到AES的key
byte[] plaintext = decryptByPrivateKey(Base64.decodeBase64(aesKey),privateKey);
aesKey = new String(plaintext);
System.out.println("RSA 解密之后:");
System.out.println(aesKey);
//AES解密得到明文data数据
String result = AESUtil.decrypt(aesKey, key);
System.out.println("AES 解密之后:");
System.out.println(result);
System.out.println("=====================私钥加密,公钥解密==================");
//随机AES的key加密后的密文
String data1 = AESUtil.encrypt("你们好啊", key);
System.out.println("AES 加密之后:");
System.out.println(data1);
//用公钥来加密AES的key,并转成Base64
String aesKey1 = Base64.encodeBase64String(privKeyEnc(data1.getBytes(),privateKey));
System.out.println("RSA 加密之后:");
System.out.println(aesKey1);
//用私钥解密到AES的key
byte[] plaintext1 = pubKeyDec(Base64.decodeBase64(aesKey1),publicKey);
aesKey1 = new String(plaintext1);
System.out.println("RSA 解密之后:");
System.out.println(aesKey1);
//AES解密得到明文data数据
String result1 = AESUtil.decrypt(aesKey1, key);
System.out.println("AES 解密之后:");
System.out.println(result1);
到这里后端配置完成



