文章目录
AES / RSA
- AES:一种对称加密算法,意味着加密和解密使用相同的密钥。速度快,适合加密大量数据。
- RSA:一种非对称加密算法,有一对密钥:公钥和私钥。用公钥加密的数据只能用对应的私钥解密,反之亦然。
流程
- 客户端和服务端都生成一对RSA密钥:- 客户端和服务端各自生成自己的RSA公钥和私钥。- RSA公钥是公开的,可以共享;RSA私钥则要保密。
- 客户端和服务端分别生成AES密钥:- 客户端和服务端都生成自己的AES密钥,用于加密实际的数据。
- 客户端发送请求给服务端:- 客户端用服务端的RSA公钥加密它自己的AES密钥,并将加密后的AES密钥发送给服务端。- 同时,客户端还会用AES密钥加密一份请求报文,然后将这个加密的报文和它自己的RSA公钥一起发送给服务端。
- 服务端解密并处理请求:- 服务端接收到请求后,用自己的RSA私钥解密客户端发送的AES密钥。- 然后,服务端用解密后的AES密钥解密客户端的请求报文,得到了客户端发送的实际信息。- 服务端接下来会生成一个响应报文,用客户端的AES密钥加密该响应报文。
- 服务端发送响应给客户端:- 服务端用客户端的RSA公钥加密自己的AES密钥,并将加密后的AES密钥和加密的响应报文一起发送给客户端。
- 客户端解密并获取响应:- 客户端用自己的RSA私钥解密服务端发送过来的AES密钥。- 然后,客户端用解密后的AES密钥解密服务端的响应报文,得到最终的回应内容。
Code
生成AES密钥 和 生成RSA密钥对
packagecom.artisan.shuangxiang_aesrsa;importjavax.crypto.KeyGenerator;importjavax.crypto.SecretKey;importjava.security.KeyPair;importjava.security.KeyPairGenerator;/**
* @author artisan
*/publicclassKeyGeneration{/**
* 生成AES密钥
*
* @return 生成的SecretKey对象,包含AES算法的密钥
* @throws Exception 如果密钥生成过程中出现错误
*/publicstaticSecretKeygenerateAESKey()throwsException{// 获取KeyGenerator实例,指定使用AES算法KeyGenerator keyGen =KeyGenerator.getInstance("AES");// 初始化AES密钥的长度为128位
keyGen.init(128);// 生成AES密钥return keyGen.generateKey();}/**
* 生成RSA密钥对
*
* @return 生成的RSA密钥对
* @throws Exception 如果无法生成密钥对,则抛出异常
*/publicstaticKeyPairgenerateRSAKeyPair()throwsException{// 获取密钥对生成器实例KeyPairGenerator keyPairGen =KeyPairGenerator.getInstance("RSA");// 初始化密钥对生成器为2048位
keyPairGen.initialize(2048);// 生成RSA密钥对return keyPairGen.generateKeyPair();}}
AES工具类,提供AES加密和解密功能
packagecom.artisan.shuangxiang_aesrsa;importjavax.crypto.Cipher;importjavax.crypto.SecretKey;importjavax.crypto.spec.IvParameterSpec;importjava.util.Base64;/**
* @author artisan
*//**
* AES工具类,提供AES加密和解密功能
* 使用AES/CBC/PKCS5Padding算法进行加密和解密
*/publicclassAESUtil{/**
* 定义加密算法类型为AES/CBC/PKCS5Padding
*/privatestaticfinalStringALGORITHM="AES/CBC/PKCS5Padding";/**
* 使用AES算法加密数据
*
* @param data 待加密的字符串
* @param key 加密使用的SecretKey
* @param iv 加密使用的初始化向量(IvParameterSpec)
* @return 加密后的字符串,以Base64编码
* @throws Exception 如果加密过程中发生错误,抛出异常
*/publicstaticStringencryptAES(String data,SecretKey key,IvParameterSpec iv)throwsException{// 创建Cipher实例,指定使用AES/CBC/PKCS5Padding算法Cipher cipher =Cipher.getInstance(ALGORITHM);// 初始化Cipher为加密模式,传入密钥和初始化向量
cipher.init(Cipher.ENCRYPT_MODE, key, iv);// 将待加密数据转换为字节数组,并执行加密操作byte[] encryptedData = cipher.doFinal(data.getBytes());// 将加密后的数据使用Base64编码,并返回returnBase64.getEncoder().encodeToString(encryptedData);}/**
* 使用AES算法解密数据
*
* @param encryptedData 待解密的字符串,以Base64编码
* @param key 解密使用的SecretKey
* @param iv 解密使用的初始化向量(IvParameterSpec)
* @return 解密后的字符串
* @throws Exception 如果解密过程中发生错误,抛出异常
*/publicstaticStringdecryptAES(String encryptedData,SecretKey key,IvParameterSpec iv)throwsException{// 创建Cipher实例,指定使用AES/CBC/PKCS5Padding算法Cipher cipher =Cipher.getInstance(ALGORITHM);// 初始化Cipher为解密模式,传入密钥和初始化向量
cipher.init(Cipher.DECRYPT_MODE, key, iv);// 将待解密数据从Base64解码为字节数组byte[] decodedData =Base64.getDecoder().decode(encryptedData);// 执行解密操作byte[] decryptedData = cipher.doFinal(decodedData);// 将解密后的数据转换为字符串,并返回returnnewString(decryptedData);}}
RSA加密工具类
packagecom.artisan.shuangxiang_aesrsa;importjavax.crypto.Cipher;importjava.security.PrivateKey;importjava.security.PublicKey;importjava.util.Base64;/**
* RSA加密工具类
* @author artisan
*/publicclassRSAUtil{/**
* 定义加密算法类型为RSA
*/privatestaticfinalStringALGORITHM="RSA";/**
* 使用RSA算法和公钥加密数据
*
* @param data 待加密的字符串数据
* @param publicKey 用于加密的公钥
* @return 加密后的数据,以Base64编码的字符串形式表示
* @throws Exception 如果加密过程中发生错误,抛出异常
*/publicstaticStringencryptRSA(String data,PublicKey publicKey)throwsException{// 获取Cipher实例,指定使用RSA算法Cipher cipher =Cipher.getInstance(ALGORITHM);// 初始化Cipher为加密模式,并使用指定的公钥
cipher.init(Cipher.ENCRYPT_MODE, publicKey);// 将待加密的字符串转换为字节数组,并执行加密操作byte[] encryptedData = cipher.doFinal(data.getBytes());// 将加密后的字节数组使用Base64编码为字符串returnBase64.getEncoder().encodeToString(encryptedData);}/**
* 使用RSA算法和私钥解密数据
*
* @param encryptedData 待解密的字符串数据,预期是通过Base64编码的
* @param privateKey 用于解密的私钥
* @return 解密后的原始字符串数据
* @throws Exception 如果解密过程中发生错误,抛出异常
*/publicstaticStringdecryptRSA(String encryptedData,PrivateKey privateKey)throwsException{// 获取Cipher实例,指定使用RSA算法Cipher cipher =Cipher.getInstance(ALGORITHM);// 初始化Cipher为解密模式,并使用指定的私钥
cipher.init(Cipher.DECRYPT_MODE, privateKey);// 将Base64编码的字符串解码为字节数组byte[] decodedData =Base64.getDecoder().decode(encryptedData);// 执行解密操作,得到原始的字节数组byte[] decryptedData = cipher.doFinal(decodedData);// 将解密后的字节数组转换为字符串returnnewString(decryptedData);}}
测试类
packagecom.artisan.shuangxiang_aesrsa;importjavax.crypto.SecretKey;importjavax.crypto.spec.IvParameterSpec;importjava.security.KeyPair;importjava.security.PrivateKey;importjava.security.PublicKey;importjava.util.Base64;/**
* @author artisan
*/publicclassMain{/**
* 使用RSA公钥加密AES密钥,以及使用RSA私钥解密AES密钥的全过程
* 同时展示了使用AES密钥加密和解密数据的应用
*
* @param args 命令行参数
* @throws Exception 可能抛出的异常
*/publicstaticvoidmain(String[] args)throwsException{// 生成AES和RSA密钥SecretKey aesKey =KeyGeneration.generateAESKey();KeyPair rsaKeyPair =KeyGeneration.generateRSAKeyPair();PublicKey rsaPublicKey = rsaKeyPair.getPublic();PrivateKey rsaPrivateKey = rsaKeyPair.getPrivate();String aesKeyString =Base64.getEncoder().encodeToString(aesKey.getEncoded());System.out.println("AES密钥: "+ aesKeyString);// 初始化IV(通常需要确保IV的安全传输) 16字节的IV向量IvParameterSpec iv =newIvParameterSpec(newbyte[16]);// 客户端用服务端的RSA公钥加密AES密钥String encryptedAESKey =RSAUtil.encryptRSA(aesKeyString, rsaPublicKey);System.out.println("加密后的AES密钥: "+ encryptedAESKey);// 模拟服务端解密AES密钥String decryptedAESKey =RSAUtil.decryptRSA(encryptedAESKey, rsaPrivateKey);SecretKey originalAESKey =newjavax.crypto.spec.SecretKeySpec(Base64.getDecoder().decode(decryptedAESKey),"AES");System.out.println("解密后的AES密钥: "+Base64.getEncoder().encodeToString(originalAESKey.getEncoded()));// 使用AES加密和解密数据String originalData ="我是需要加密的数据artisan GO GO GO !!!";String encryptedData =AESUtil.encryptAES(originalData, aesKey, iv);System.out.println("加密的数据: "+ encryptedData);String decryptedData =AESUtil.decryptAES(encryptedData, aesKey, iv);System.out.println("解密的数据: "+ decryptedData);}}
输出
AES密钥: n5PbFsDPACXiDsuBhjHwvg==
加密后的AES密钥: cuNuyggZpGhVthHpUPEEt7l7Nh9ySl4S4zLBVLpxbx3ft9JwKNfTi0ggtAX1p27lpFsru/riYVv/6HuI/AO2PV/WzmE9ySUa7+cdkvlTqdbsQaFF67R2DqEtMbsJyfiGVI6Y9acObMWw9nGeggtsQAlfNqjV8LC8i1T4OJcstMcmdgCEg85vBizwdFEOJPZO1SDEd///CY2jT7tY7Zz4kvq9f+WkNnHy+s11cUOzr6Griv83JlFNPvJ3DifVhkmxsR5Cg9HaRtjSRvx9VPfwza/SrQWue7rzsLSirXsj+kIOBfOopSFj0xSBCG32NnQEuWspSGdgJTHAmD/X7RJzoQ==
解密后的AES密钥: n5PbFsDPACXiDsuBhjHwvg==
加密的数据: a1gn+70y0nkd9VGg3hg3Y/b0PxUd1dqAuzKHDedGMdleu2UVWkBtInZ0Ox4iNOFM
解密的数据: 我是需要加密的数据artisan GOGOGO!!!
总结
这个流程的核心在于:
- 使用RSA来安全地交换AES密钥。
- AES用来加密实际的数据,确保数据传输的安全性和效率
- 请注意保护好自己的私钥,不可泄露
通过这种双向加密的方式,客户端和服务端能够安全地互相传递敏感信息,同时确保即使通信内容被截获,也无法被解读。
本文转载自: https://blog.csdn.net/yangshangwei/article/details/141361253
版权归原作者 小小工匠 所有, 如有侵权,请联系我们删除。
版权归原作者 小小工匠 所有, 如有侵权,请联系我们删除。