客户端服务端RSA+AES加密解密

522 阅读3分钟

需求&实现思路

工作中遇到一个需求,服务端需要将数据加密返回给客户端,查资料发现一般都是RSA+AES方式,记录一下思路和实现,后续补充一下加密的一些知识。。。

Java工具类代码

@Slf4j
public class CipherUtils {

    public static class AESUtils {
        /**
         * 算法名字
         */
        private static final String AES_ALGORITHM = "AES";
        /**
         * 算法/模式/填充
         */
        private static final String AES_TRANSFORMATION = "AES/ECB/PKCS5Padding";
        /**
         * 密钥长度16字节,128位
         */
        private static final int AES_KEY_LENGTH = 16;

        /**
         * 构建SecretKey
         *
         * @param aesKey AES密钥
         * @return
         */
        private static SecretKeySpec doSecretKeySpec(String aesKey) {
            try {
                byte[] aesKeyBytes = aesKey.getBytes(StandardCharsets.UTF_8);
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                aesKeyBytes = md.digest(aesKeyBytes);
                byte[] keyBytes16 = Arrays.copyOf(aesKeyBytes, AES_KEY_LENGTH);
                return new SecretKeySpec(keyBytes16, AES_ALGORITHM);
            } catch (NoSuchAlgorithmException e) {
                log.warn("init secretKeySpec error, ex:{}", e.getMessage());
            }
            return null;
        }

        /**
         * AES 加密
         *
         * @param data   明文数据
         * @param aesKey AES密钥
         * @return
         */
        public static String encrypt(String data, String aesKey) {
            SecretKeySpec secretKeySpec = doSecretKeySpec(aesKey);
            if (secretKeySpec != null) {
                try {
                    // 获取加密器,使用ECB模式
                    Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION);
                    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
                    // 加密明文数据
                    byte[] encryptBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
                    // base64编码
                    return Base64.getUrlEncoder().encodeToString(encryptBytes);
                } catch (Exception e) {
                    log.warn("encrypt error, ex:{}", e.getMessage());
                }
            }
            return null;
        }

        /**
         * AES 解密
         *
         * @param data   密文
         * @param aesKey AES密钥
         * @return
         */
        public static String decrypt(String data, String aesKey) {
            SecretKeySpec secretKeySpec = doSecretKeySpec(aesKey);
            if (secretKeySpec != null) {
                try {
                    // base64 解码
                    byte[] decodeBytes = Base64.getUrlDecoder().decode(data);
                    // 获取加密器,使用ECB模式
                    Cipher cipher = Cipher.getInstance(AES_TRANSFORMATION);
                    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
                    // 解密密文
                    byte[] decryptBytes = cipher.doFinal(decodeBytes);
                    return new String(decryptBytes);
                } catch (Exception e) {
                    log.warn("encrypt error, ex:{}", e.getMessage());
                }
            }
            return null;
        }
    }

    public static class RSAUtils {
        /**
         * 算法名字
         */
        private static final String RSA_ALGORITHM = "RSA";

        /**
         * 消息摘要算法
         */
        private static final String MD_ALGORITHM = "MD5withRSA";

        /**
         * RSA最大加密明文大小
         */
        private static final int MAX_ENCRYPT_BLOCK = 117;

        /**
         * RSA最大解密密文大小
         */
        private static final int MAX_DECRYPT_BLOCK = 128;

        
        /**
         * 获取RAS密钥对
         *
         * @return
         */
        public static KeyPair getKeyPair() {
            try {
                KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA_ALGORITHM);
                keyPairGenerator.initialize(1024);
                return keyPairGenerator.generateKeyPair();
            } catch (NoSuchAlgorithmException e) {
                log.warn("init RSA key pair error, ex:{}", e.getMessage());
            }
            return null;
        }

        /**
         * 制作私钥
         *
         * @param privateKey
         * @return
         */
        private static PrivateKey getPrivateKey(String privateKey) {
            try {
                KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
                byte[] privateKeyBytes = Base64.getDecoder().decode(privateKey.getBytes(StandardCharsets.UTF_8));
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
                return keyFactory.generatePrivate(keySpec);
            } catch (Exception e) {
                log.warn("init private key error, ex:{}", e.getMessage());
            }
            return null;
        }

        /**
         * 制作公钥
         *
         * @param publicKey
         * @return
         */
        private static PublicKey getPublicKey(String publicKey) {
            try {
                KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
                byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey.getBytes(StandardCharsets.UTF_8));
                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
                return keyFactory.generatePublic(keySpec);
            } catch (Exception e) {
                log.warn("init public key error, ex:{}", e.getMessage());
            }
            return null;
        }


        /**
         * RSA加密
         *
         * @param data      待加密数据
         * @param publicKey 公钥
         * @return
         */
        public static String encrypt(String data, String publicKey) {
            try {
                if (getPublicKey(publicKey) == null) {
                    return null;
                }
                Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
                cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(publicKey));
                int inputLen = data.getBytes().length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offset = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段加密
                while (inputLen - offset > 0) {
                    if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
                        cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
                    } else {
                        cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offset = i * MAX_ENCRYPT_BLOCK;
                }
                byte[] encryptedData = out.toByteArray();
                out.close();
                // 获取加密内容使用base64进行编码,并以UTF-8为标准转化成字符串
                // 加密后的字符串
                return Base64.getUrlEncoder().encodeToString(encryptedData);
            } catch (Exception e) {
                log.warn("encrypt error, ex:{}", e.getMessage());
            }
            return null;
        }

        /**
         * RSA解密
         *
         * @param data       待解密数据
         * @param privateKey 私钥
         * @return
         */
        public static String decrypt(String data, String privateKey) {
            try {
                if (getPrivateKey(privateKey) == null) {
                    return null;
                }
                Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
                byte[] dataBytes = Base64.getUrlDecoder().decode(data);
                int inputLen = dataBytes.length;
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                int offset = 0;
                byte[] cache;
                int i = 0;
                // 对数据分段解密
                while (inputLen - offset > 0) {
                    if (inputLen - offset > MAX_DECRYPT_BLOCK) {
                        cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
                    } else {
                        cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
                    }
                    out.write(cache, 0, cache.length);
                    i++;
                    offset = i * MAX_DECRYPT_BLOCK;
                }
                out.close();
                // 解密后的内容
                return out.toString("UTF-8");
            } catch (Exception e) {
                log.warn("decrypt error, ex:{}", e.getMessage());
            }
            return null;
        }

        /**
         * 签名
         *
         * @param data       待签名数据
         * @param privateKey 私钥
         * @return 签名
         */
        public static String sign(String data, PrivateKey privateKey) {
            try {
                byte[] keyBytes = privateKey.getEncoded();
                PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
                KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
                PrivateKey key = keyFactory.generatePrivate(keySpec);
                Signature signature = Signature.getInstance(MD_ALGORITHM);
                signature.initSign(key);
                signature.update(data.getBytes());
                return Base64.getUrlEncoder().encodeToString(signature.sign());
            } catch (Exception e) {
                log.warn("RSA sign error, ex:{}", e.getMessage());
            }
            return null;
        }

        /**
         * 验签
         *
         * @param srcData   原始字符串
         * @param publicKey 公钥
         * @param sign      签名
         * @return 是否验签通过
         */
        public static boolean verify(String srcData, PublicKey publicKey, String sign) {
            try {
                byte[] keyBytes = publicKey.getEncoded();
                X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
                KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
                PublicKey key = keyFactory.generatePublic(keySpec);
                Signature signature = Signature.getInstance(MD_ALGORITHM);
                signature.initVerify(key);
                signature.update(srcData.getBytes());
                return signature.verify(Base64.getUrlDecoder().decode(sign.getBytes()));
            } catch (Exception e) {
                log.warn("RSA verify error, ex:{}", e.getMessage());
            }
            return false;
        }

    }

    public static void main(String[] args) {
        String aesKey = "dmd23dewfwf2";
        String data = "1234567789sdgfhg";
        String encrypt = AESUtils.encrypt(data, aesKey);
//        System.out.println("encrypt -> " + encrypt);
        String decrypt = AESUtils.decrypt(encrypt, aesKey);
//        System.out.println("decrypt -> " + decrypt);

        KeyPair keyPair = RSAUtils.getKeyPair();
        assert keyPair != null;
        String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
        String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
        System.out.println(publicKey);
        System.out.println(privateKey);
//
//        String encrypt1 = RSAUtils.encrypt(aesKey, publicKey);
//        System.out.println("encrypt -> " + encrypt1);
//        String decrypt1 = RSAUtils.decrypt(encrypt1, privateKey);
//        System.out.println("decrypt -> " + decrypt1);

    }
}

原理(慢慢补充)