栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

spring boot 实现 RSA + AES 混合加解密案例

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring boot 实现 RSA + AES 混合加解密案例

# 前言
在我们平时项目开发过程中,经常会遇到各种各样的数据安全问题,为了防止我们的业务数据不被泄露,提高我们系统的安全性。在数据传输的时候我们对传输的数据进行加密,这里采用了 RSA (非对称) + AES (对称加密)的方式。
  • RSA:非对称加密,公钥(Public Key)与私钥(Private Key)是通过一种算法得到的一个密钥对(即一个公钥和一个私钥),公钥是密钥对中公开的部分,私钥则是非公开的部分。公钥通常用于加密会话密钥、验证数字签名,或加密可以用相应的私钥解密的数据。
  • AES:对称加密,对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。对称加密通常使用的是相对较小的密钥,一般小于256 bit。因为密钥越大,加密越强,但加密与解密的过程越慢。
之所以用 AES 加密数据是因为效率高,RSA 运行速度慢,我们可以采用这两种算法互补,来保证安全性,用 RSA 来加密传输 AES 的秘钥,用 AES 来加密数据,两者相互结合,优势互补。 # 大致思路
  1. 客户端启动,发送请求到服务端,服务端用 RSA 算法生成一对公钥和私钥,我们简称为publickey1,privatekey2,将公钥 publickey1 返回给客户端。
  2. 客户端拿到服务端返回的公钥 publickey1 后,自己用 RSA 算法生成一对公钥和私钥,我们简称为publickey2,privatekey2,并将公钥 publickey2通过公钥 publickey1加密,加密之后传输给服务端。
  3. 此时服务端收到客户端传输的密文,用私钥 privatekey1 进行解密,因为数据是用公钥 publickey1 加密的,通过解密就可以得到客户端生成的公钥 publickey2 。
  4. 然后自己在生成对称加密,也就是我们的 AES,其实也就是相对于我们配置中的那个 16 的长度的加密 key,生成了这个 key 之后我们就用公钥 publickey2 进行加密,返回给客户端,因为只有客户端有publickey2 对应的私钥 privatekey2,只有客户端才能解密。
  5. 客户端得到数据之后,用 privatekey2 进行解密操作,得到 AES 的加密 key,最后就用加密 key 进行数据传输的加密,至此整个流程结束。
这里只是实现的大致流程,最终还是根据自己的业务需要来实现。 这里主要对后端的实现,前端的话大家可以自己去了解一下,这里不过多的介绍了! # 工具类 ## AES工具类 AESUtil ```c //日志 private static final Logger logger = LoggerFactory.getLogger(AESUtil.class); private static final String KEY_ALGORITHM = "AES"; private static final int KEY_LENGTH = 16 * 8; private static final String ALGORITHMS = "AES/ECB/PKCS5Padding"; public static String key; private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider(); static { key = getKey(); } public static String getKey() { int length = KEY_LENGTH / 8; StringBuilder uid = new StringBuilder(length); //产生16位的强随机数 Random rd = new SecureRandom(); for (int i = 0; i < length; i++) { //产生0-2的3位随机数 switch (rd.nextInt(3)) { case 0: //0-9的随机数 uid.append(rd.nextInt(10)); break; case 1: //ASCII在65-90之间为大写,获取大写随机 uid.append((char) (rd.nextInt(26) + 65)); break; case 2: //ASCII在97-122之间为小写,获取小写随机 uid.append((char) (rd.nextInt(26) + 97)); break; default: break; } } return uid.toString(); } 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 // 转base64 return Base64.encodeBase64String(cipher.doFinal(content.getBytes(StandardCharsets.UTF_8))); } public static String decrypt(String encryptStr, String decryptKey) throws Exception { //base64格式的key字符串转byte byte[] 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)); }
AES 测试类
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);

到这里后端配置完成

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1041114.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号