素材巴巴 > 程序开发 >

rsa aes加密

程序开发 2023-09-09 18:24:59

参考:https://www.cnblogs.com/huanzi-qch/p/10913636.html

这里只讨论java代码,详情请看:前后端API交互数据加密——AES与RSA混合加密完整实例

AES简介

高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:

在这里插入图片描述

RSA加密

RSA公钥加密算法是1977年由Ron Rivest、Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的。RSA取名来自开发他们三者的名字。RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

RSA公开密钥密码体制。所谓的公开密钥密码体制就是使用不同的加密密钥与解密密钥,是一种“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制。

在这里插入图片描述

AES+RSA=数据加密方案:

在这里插入图片描述
流程:

接收方创建RSA秘钥对,

发送RSA公钥给发送方,自己保留RSA私钥

发送方创建AES密钥,加密待传送的明文,之后用RSA公钥加密该密钥,

RSA公钥加密AES的密钥+AES密钥加密明文的密文----通过Internet发给---->接收方

接收方用RSA私钥解密加密的密钥,之后再用解密后的AES密钥解密数据密文,得到明文。

AES和RSAjava实现代码实例

pom:

 org.apache.directory.studioorg.apache.commons.codec1.8
 

AESUtil:

package com.example.utils.jiamiUtil.encrypt.utils;import org.apache.tomcat.util.codec.binary.Base64;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
 import javax.crypto.spec.SecretKeySpec;
 import java.nio.charset.StandardCharsets;
 import java.security.SecureRandom;
 import java.util.Random;//参考:https://www.cnblogs.com/huanzi-qch/p/10913636.html
 /*** AES加、解密算法工具类*/
 public class AesUtil {/*** 加密算法AES*/private static final String KEY_ALGORITHM = "AES";/*** key的长度,Wrong key size: must be equal to 128, 192 or 256* 传入时需要16、24、36*/private static final Integer KEY_LENGTH = 16 * 8;/*** 算法名称/加密模式/数据填充方式* 默认:AES/ECB/PKCS5Padding*/private static final String ALGORITHMS = "AES/ECB/PKCS5Padding";
 //    private static final String ALGORITHMS = "AES/ECB/PKCS7Padding";/*** 后端AES的key,由静态代码块赋值*/public static String key;/*** 不能在代码中创建* JceSecurity.getVerificationResult 会将其put进 private static final Map中,导致内存缓便被耗尽*/private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider();static {key = getKey();}/*** 获取key*/public static String getKey() {StringBuilder uid = new StringBuilder();//产生16位的强随机数Random rd = new SecureRandom();for (int i = 0; i < KEY_LENGTH / 8; i++) {//产生0-2的3位随机数int type = rd.nextInt(3);switch (type) {case 0://0-9的随机数uid.append(rd.nextInt(10));break;case 1://ASCII在65-90之间为大写,获取大写随机uid.append((char) (rd.nextInt(25) + 65));break;case 2://ASCII在97-122之间为小写,获取小写随机uid.append((char) (rd.nextInt(25) + 97));break;default:break;}}return uid.toString();}/*** 加密** @param content    加密的字符串* @param encryptKey key值*/public static String encrypt(String content, String encryptKey) throws Exception {//设置Cipher对象Cipher cipher = Cipher.getInstance(ALGORITHMS, PROVIDER);cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), KEY_ALGORITHM));//调用doFinal// 转base64return Base64.encodeBase64String(cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)));}/*** 解密** @param encryptStr 解密的字符串* @param decryptKey 解密的key值*/public static String decrypt(String encryptStr, String decryptKey) throws Exception {//base64格式的key字符串转bytebyte[] decodeBase64 = Base64.decodeBase64(encryptStr);//设置Cipher对象Cipher cipher = Cipher.getInstance(ALGORITHMS,PROVIDER);cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), KEY_ALGORITHM));//调用doFinal解密return new String(cipher.doFinal(decodeBase64));}}
 

RSAUtil:

package com.example.utils.jiamiUtil.encrypt.utils;import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;
 import java.io.ByteArrayOutputStream;
 import java.security.Key;
 import java.security.KeyFactory;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.interfaces.RSAPrivateKey;
 import java.security.interfaces.RSAPublicKey;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;/*** RSA加、解密算法工具类*/
 @Slf4j
 public class RsaUtil {/*** 加密算法AES*/private static final String KEY_ALGORITHM = "RSA";/*** RSA 位数 如果采用2048 上面最大加密和最大解密则须填写:  245 256*/private static final int INITIALIZE_LENGTH = 1024;/*** 算法名称/加密模式/数据填充方式* 默认:RSA/ECB/PKCS1Padding*/private static final String ALGORITHMS = "RSA/ECB/PKCS1Padding";
 //    private static final String ALGORITHMS = "RSA/ECB/PKCS7Padding";/*** Map获取公钥的key*/private static final String PUBLIC_KEY = "publicKey";/*** Map获取私钥的key*/private static final String PRIVATE_KEY = "privateKey";/*** RSA最大加密明文大小*/private static final int MAX_ENCRYPT_BLOCK = 117;/*** RSA最大解密密文大小*/private static final int MAX_DECRYPT_BLOCK = 128;/*** 后端RSA的密钥对(公钥和私钥)Map,由静态代码块赋值*/private static Map genKeyPair = new LinkedHashMap<>();static {try {genKeyPair.putAll(genKeyPair());} catch (Exception e) {//输出到日志文件中log.error(ErrorUtil.errorInfoToString(e));}}/*** 生成密钥对(公钥和私钥)*/private 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();Map keyMap = new HashMap(2);//公钥keyMap.put(PUBLIC_KEY, publicKey);//私钥keyMap.put(PRIVATE_KEY, privateKey);return keyMap;}/*** 私钥解密** @param encryptedData 已加密数据* @param privateKey    私钥(BASE64编码)*/public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {//base64格式的key字符串转Key对象Key privateK = KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));//设置加密、填充方式/*如需使用更多加密、填充方式,引入org.bouncycastlebcprov-jdk161.46并改成Cipher cipher = Cipher.getInstance(ALGORITHMS ,new BouncyCastleProvider());*/Cipher cipher = Cipher.getInstance(ALGORITHMS);cipher.init(Cipher.DECRYPT_MODE, privateK);//分段进行解密操作return encryptAndDecryptOfSubsection(encryptedData, cipher, MAX_DECRYPT_BLOCK);}/*** 公钥加密** @param data      源数据* @param publicKey 公钥(BASE64编码)*/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)));//设置加密、填充方式/*如需使用更多加密、填充方式,引入org.bouncycastlebcprov-jdk161.46并改成Cipher cipher = Cipher.getInstance(ALGORITHMS ,new BouncyCastleProvider());*/Cipher cipher = Cipher.getInstance(ALGORITHMS);cipher.init(Cipher.ENCRYPT_MODE, publicK);//分段进行加密操作return encryptAndDecryptOfSubsection(data, cipher, MAX_ENCRYPT_BLOCK);}/*** 获取私钥*/public static String getPrivateKey() {Key key = (Key) genKeyPair.get(PRIVATE_KEY);return Base64.encodeBase64String(key.getEncoded());}/*** 获取公钥*/public static String getPublicKey() {Key key = (Key) genKeyPair.get(PUBLIC_KEY);return Base64.encodeBase64String(key.getEncoded());}/*** 分段进行加密、解密操作*/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对称加密、解密简单测试

1、字符串

package com.example.utils.jiamiUtil.encrypt.test.aestest;import com.example.utils.jiamiUtil.encrypt.utils.AesUtil;public class AestestString {public static void main(String[] args) {//16位
 //        String key = "MIGfMA0GCSqGSIb3";String key = AesUtil.getKey();System.out.println("key == "+key);//字符串String str = "huanzi.qch@qq.com:欢子";try {//加密String encrypt = AesUtil.encrypt(str, key);//解密String decrypt = AesUtil.decrypt(encrypt, key);System.out.println("加密前:" + str);System.out.println("加密后:" + encrypt);System.out.println("解密后:" + decrypt);} catch (Exception e) {e.printStackTrace();}}}
 

在这里插入图片描述

2、复杂对象

package com.example.utils.jiamiUtil.encrypt.test.aestest;import com.example.utils.jiamiUtil.encrypt.test.vo.ImsUserVo;
 import com.example.utils.jiamiUtil.encrypt.utils.AesUtil;public class AestestObject {public static void main(String[] args) {//16位  只要是16位就可以
 //        String key = "MIGfMA0GCSqGSIb3";String key = "MIGfMA0GCSqGSIb1";//复杂对象ImsUserVo userVo = new ImsUserVo();userVo.setUserName("123456");userVo.setPassword("111111");try {//加密String encrypt = AesUtil.encrypt(userVo.toString(), key);//解密String decrypt = AesUtil.decrypt(encrypt, key);System.out.println("加密前:" + userVo.toString());System.out.println("加密后:" + encrypt);System.out.println("解密后:" + decrypt);} catch (Exception e) {e.printStackTrace();}}}
 

在这里插入图片描述

RAS非对称加密、解密简单测试

1、字符串的RSA公钥加密、私钥解密

package com.example.utils.jiamiUtil.encrypt.test.rastest;import com.example.utils.jiamiUtil.encrypt.utils.RsaUtil;
 import org.apache.commons.codec.binary.Base64;public class RASTestString {public static void main(String[] args) {//字符串String str = "huanzi.qch@qq.com:欢子";try {System.out.println("私钥:" + RsaUtil.getPrivateKey());System.out.println("公钥:" + RsaUtil.getPublicKey());//公钥加密byte[] ciphertext = RsaUtil.encryptByPublicKey(str.getBytes(), RsaUtil.getPublicKey());//私钥解密byte[] plaintext = RsaUtil.decryptByPrivateKey(ciphertext, RsaUtil.getPrivateKey());System.out.println("公钥加密前:" + str);System.out.println("公钥加密后:" + Base64.encodeBase64String(ciphertext));System.out.println("私钥解密后:" + new String(plaintext));} catch (Exception e) {e.printStackTrace();}}}
 

在这里插入图片描述

2、复杂对象的RSA公钥加密、私钥解密

package com.example.utils.jiamiUtil.encrypt.test.rastest;import com.example.utils.jiamiUtil.encrypt.test.vo.ImsUserVo;
 import com.example.utils.jiamiUtil.encrypt.utils.RsaUtil;
 import org.apache.commons.codec.binary.Base64;public class RASTestObject {public static void main(String[] args) {//复杂对象ImsUserVo userVo = new ImsUserVo();userVo.setUserName("12345");userVo.setPassword("11111");try {System.out.println("私钥:" + RsaUtil.getPrivateKey());System.out.println("公钥:" + RsaUtil.getPublicKey());//公钥加密byte[] ciphertext = RsaUtil.encryptByPublicKey(userVo.toString().getBytes(), RsaUtil.getPublicKey());//私钥解密byte[] plaintext = RsaUtil.decryptByPrivateKey(ciphertext, RsaUtil.getPrivateKey());System.out.println("公钥加密前:" + userVo.toString());System.out.println("公钥加密后:" + Base64.encodeBase64String(ciphertext));System.out.println("私钥解密后:" + new String(plaintext));} catch (Exception e) {e.printStackTrace();}}}
 

在这里插入图片描述


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。