# 前言 在我们平时项目开发过程中,经常会遇到各种各样的数据安全问题,为了防止我们的业务数据不被泄露,提高我们系统的安全性。在数据传输的时候我们对传输的数据进行加密,这里采用了 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 MapRSA + AES 测试类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(); }
//随机获取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);
到这里后端配置完成