java实现双向ECC + AES加密

本文补充了《java实现双向RSA + AES加密》的内容,重点介绍如何使用bouncycastle库实现在Java中进行双向椭圆曲线(ECC)加密解密。首先,需要解除JDK默认加密强度限制,然后下载并替换JDK安全目录中的jar包,接着引入bouncycastle库。提供了ECCUtil和HttpEncryptUtil的代码示例。
摘要由CSDN通过智能技术生成

本文主要是前面《java实现双向RSA + AES加密》的补充,只补充新增的代码,


JDK中自带了椭圆曲线的签名,但是没有实现椭圆曲线的加密解密。不过bouncycastle库实现了,下面的代码需要bouncycastle库。

需要做的准备工作:


1. 去JDK的下载页面,下载


http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html 

这个东西。这个是为了解除默认JDK中的加密强度的限制。不使用这个可能会报错。

下载下来以后,需要将local_policy.jar 和 US_export_policy.jar替换掉D:\Program Files\Java\jdk1.8.0_91\jre\lib\security下面的相同的两个jar包。


2. 下载bouncycastle的jar文件,加入classpath中。

http://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on 


下面上代码

ECCUtil:

package com.zhuyun.encrypt;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;


public class ECCUtil {
	static {
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
	}
	
	//生成秘钥对
	public static KeyPair getKeyPair() throws Exception {
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
		keyPairGenerator.initialize(256, new SecureRandom());
		KeyPair keyPair = keyPairGenerator.generateKeyPair();
		return keyPair;
	}
	
	//获取公钥(Base64编码)
	public static String getPublicKey(KeyPair keyPair){
		ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
		byte[] bytes = publicKey.getEncoded();
		return AESUtil.byte2Base64(bytes);
	}
	
	//获取私钥(Base64编码)
	public static String getPrivateKey(KeyPair keyPair){
		ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate();
		byte[] bytes = privateKey.getEncoded();
		return AESUtil.byte2Base64(bytes);
	}
	
	//将Base64编码后的公钥转换成PublicKey对象
	public static ECPublicKey string2PublicKey(String pubStr) throws Exception{
		byte[] keyBytes = AESUtil.base642Byte(pubStr);
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
		ECPublicKey publicKey = (ECPublicKey) keyFactory.generatePublic(keySpec);
		return publicKey;
	}
	
	//将Base64编码后的私钥转换成PrivateKey对象
	public static ECPrivateKey string2PrivateKey(String priStr) throws Exception{
		byte[] keyBytes = AESUtil.base642Byte(priStr);
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance("EC", "BC");
		ECPrivateKey privateKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
		return privateKey;
	}
	
	//公钥加密
	public static byte[] publicEncrypt(byte[] content, PublicKey publicKey) throws Exception{
		Cipher cipher = Cipher.getInstance("ECIES", "BC");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		byte[] bytes = cipher.doFinal(content);
		return bytes;
	}
	
	//私钥解密
	public static byte[] privateDecrypt(byte[] content, PrivateKey privateKey) throws Exception{
		Cipher cipher = Cipher.getInstance("ECIES", "BC");
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		byte[] bytes = cipher.doFinal(content);
		return bytes;
	}
	
	public static void main(String[] args) throws Exception {
		KeyPair keyPair = ECCUtil.getKeyPair();
		String publicKeyStr = ECCUtil.getPublicKey(keyPair);
		String privateKeyStr = ECCUtil.getPrivateKey(keyPair);
		System.out.println("ECC公钥Base64编码:" + publicKeyStr);
		System.out.println("ECC私钥Base64编码:" + privateKeyStr);
		
		ECPublicKey publicKey = string2PublicKey(publicKeyStr);
		ECPrivateKey privateKey = string2PrivateKey(privateKeyStr);
		
		byte[] publicEncrypt = publicEncrypt("hello world".getBytes(), publicKey);
		byte[] privateDecrypt = privateDecrypt(publicEncrypt, privateKey);
		System.out.println(new String(privateDecrypt));
	}
}



封装好的类 HttpEncryptUtil:

package com.zhuyun.encrypt;

import java.security.PrivateKey;
import java.security.PublicKey;

import javax.crypto.SecretKey;

import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;


import net.sf.json.JSONObject;


public class HttpEncryptUtil {

//	//################################双向RSA + AES ##########################
//	//APP加密请求内容
//	public static String appEncrypt(String appPublicKeyStr, String content) throws Exception{
//		//将Base64编码后的Server公钥转换成PublicKey对象
//		PublicKey serverPublicKey = RSAUtil.string2PublicKey(KeyUtil.SERVER_PUBLIC_KEY);
//		//每次都随机生成AES秘钥
//		String aesKeyStr = AESUtil.genKeyAES();
//		SecretKey aesKey = AESUtil.loadKeyAES(aesKeyStr);
//		//用Server公钥加密AES秘钥
//		byte[] encryptAesKey = RSAUtil.publicEncrypt(aesKeyStr.getBytes(), serverPublicKey);
//		//用AES秘钥加密APP公钥
//		byte[] encryptAppPublicKey = AESUtil.encryptAES(appPublicKeyStr.getBytes(), aesKey);
//		//用AES秘钥加密请求内容
//		byte[] encryptRequest = AESUtil.encryptAES(content.getBytes(), aesKey);
//		
//		JSONObject result = new JSONObject();
//		result.put("ak", RSAUtil.byte2Base64(encryptAesKey).replaceAll("\r\n", ""));
//		result.put("apk", RSAUtil.byte2Base64(encryptAppPublicKey).replaceAll("\r\n", ""));
//		result.put("ct", RSAUtil.byte2Base64(encryptRequest).replaceAll("\r\n", ""));
//		return result.toString();
//	}
//	
//	//APP解密服务器的响应内容
//	public static String appDecrypt(String appPrivateKeyStr, String content) throws Exception{
//		JSONObject result = JSONObject.fromObject(content);
//		String encryptAesKeyStr = (String) result.get("ak");
//		String encryptContent = (String) result.get("ct");
//		
//		//将Base64编码后的APP私钥转换成PrivateKey对象
//		PrivateKey appPrivateKey = RSAUtil.string2PrivateKey(appPrivateKeyStr);
//		//用APP私钥解密AES秘钥
//		byte[] aesKeyBytes = RSAUtil.privateDecrypt(RSAUtil.base642Byte(encryptAesKeyStr), appPrivateKey);
//		//用AES秘钥解密请求内容
//		SecretKey aesKey = AESUtil.loadKeyAES(new String(aesKeyBytes));
//		byte[] response = AESUtil.decryptAES(RSAUtil.base642Byte(encryptContent), aesKey);
//		
//		return new String(response);
//	}
//	
//	//服务器加密响应给APP的内容
//	public static String serverEncrypt(String appPublicKeyStr, String aesKeyStr, String content) throws Exception{
//		//将Base64编码后的APP公钥转换成PublicKey对象
//		PublicKey appPublicKey = RSAUtil.string2PublicKey(appPublicKeyStr);
//		//将Base64编码后的AES秘钥转换成SecretKey对象
//		SecretKey aesKey = AESUtil.loadKeyAES(aesKeyStr);
//		//用APP公钥加密AES秘钥
//		byte[] encryptAesKey = RSAUtil.publicEncrypt(aesKeyStr.getBytes(), appPublicKey);
//		//用AES秘钥加密响应内容
//		byte[] encryptContent = AESUtil.encryptAES(content.getBytes(), aesKey);
//		
//		JSONObject result = new JSONObject();
//		result.put("ak", RSAUtil.byte2Base64(encryptAesKey).replaceAll("\r\n", ""));
//		result.put("ct", RSAUtil.byte2Base64(encryptContent).replaceAll("\r\n", ""));
//		return result.toString();
//	}
//	
//	//服务器解密APP的请求内容
//	public static String serverDecrypt(String content) throws Exception{
//		JSONObject result = JSONObject.fromObject(content);
//		String encryptAesKeyStr = (String) result.get("ak");
//		String encryptAppPublicKeyStr = (String) result.get("apk");
//		String encryptContent = (String) result.get("ct");
//		
//		//将Base64编码后的Server私钥转换成PrivateKey对象
//		PrivateKey serverPrivateKey = RSAUtil.string2PrivateKey(KeyUtil.SERVER_PRIVATE_KEY);
//		//用Server私钥解密AES秘钥
//		byte[] aesKeyBytes = RSAUtil.privateDecrypt(RSAUtil.base642Byte(encryptAesKeyStr), serverPrivateKey);
//		//用Server私钥解密APP公钥
//		SecretKey aesKey = AESUtil.loadKeyAES(new String(aesKeyBytes));
//		byte[] appPublicKeyBytes = AESUtil.decryptAES(RSAUtil.base642Byte(encryptAppPublicKeyStr), aesKey);
//		//用AES秘钥解密请求内容
//		byte[] request = AESUtil.decryptAES(RSAUtil.base642Byte(encryptContent), aesKey);
//		
//		JSONObject result2 = new JSONObject();
//		result2.put("ak", new String(aesKeyBytes));
//		result2.put("apk", new String(appPublicKeyBytes));
//		result2.put("ct", new String(request));
//		return result2.toString();
//	}
	
	
	//################################双向ECC + AES ##########################
	//APP加密请求内容
	public static String appEncrypt(String appPublicKeyStr, String content) throws Exception{
		//将Base64编码后的Server公钥转换成PublicKey对象
		ECPublicKey serverPublicKey = ECCUtil.string2PublicKey(KeyUtil.SERVER_PUBLIC_KEY);
		//每次都随机生成AES秘钥
		String aesKeyStr = AESUtil.genKeyAES();
		SecretKey aesKey = AESUtil.loadKeyAES(aesKeyStr);
		//用Server公钥加密AES秘钥
		byte[] encryptAesKey = ECCUtil.publicEncrypt(aesKeyStr.getBytes(), serverPublicKey);
		//用AES秘钥加密APP公钥
		byte[] encryptAppPublicKey = AESUtil.encryptAES(appPublicKeyStr.getBytes(), aesKey);
		//用AES秘钥加密请求内容
		byte[] encryptRequest = AESUtil.encryptAES(content.getBytes(), aesKey);
		
		JSONObject result = new JSONObject();
		result.put("ak", AESUtil.byte2Base64(encryptAesKey).replaceAll("\r\n", ""));
		result.put("apk", AESUtil.byte2Base64(encryptAppPublicKey).replaceAll("\r\n", ""));
		result.put("ct", AESUtil.byte2Base64(encryptRequest).replaceAll("\r\n", ""));
		return result.toString();
	}
	
	//APP解密服务器的响应内容
	public static String appDecrypt(String appPrivateKeyStr, String content) throws Exception{
		JSONObject result = JSONObject.fromObject(content);
		String encryptAesKeyStr = (String) result.get("ak");
		String encryptContent = (String) result.get("ct");
		
		//将Base64编码后的APP私钥转换成PrivateKey对象
		ECPrivateKey appPrivateKey = ECCUtil.string2PrivateKey(appPrivateKeyStr);
		//用APP私钥解密AES秘钥
		byte[] aesKeyBytes = ECCUtil.privateDecrypt(AESUtil.base642Byte(encryptAesKeyStr), appPrivateKey);
		//用AES秘钥解密请求内容
		SecretKey aesKey = AESUtil.loadKeyAES(new String(aesKeyBytes));
		byte[] response = AESUtil.decryptAES(AESUtil.base642Byte(encryptContent), aesKey);
		
		return new String(response);
	}
	
	//服务器加密响应给APP的内容
	public static String serverEncrypt(String appPublicKeyStr, String aesKeyStr, String content) throws Exception{
		//将Base64编码后的APP公钥转换成PublicKey对象
		ECPublicKey appPublicKey = ECCUtil.string2PublicKey(appPublicKeyStr);
		//将Base64编码后的AES秘钥转换成SecretKey对象
		SecretKey aesKey = AESUtil.loadKeyAES(aesKeyStr);
		//用APP公钥加密AES秘钥
		byte[] encryptAesKey = ECCUtil.publicEncrypt(aesKeyStr.getBytes(), appPublicKey);
		//用AES秘钥加密响应内容
		byte[] encryptContent = AESUtil.encryptAES(content.getBytes(), aesKey);
		
		JSONObject result = new JSONObject();
		result.put("ak", AESUtil.byte2Base64(encryptAesKey).replaceAll("\r\n", ""));
		result.put("ct", AESUtil.byte2Base64(encryptContent).replaceAll("\r\n", ""));
		return result.toString();
	}
	
	//服务器解密APP的请求内容
	public static String serverDecrypt(String content) throws Exception{
		JSONObject result = JSONObject.fromObject(content);
		String encryptAesKeyStr = (String) result.get("ak");
		String encryptAppPublicKeyStr = (String) result.get("apk");
		String encryptContent = (String) result.get("ct");
		
		//将Base64编码后的Server私钥转换成PrivateKey对象
		ECPrivateKey serverPrivateKey = ECCUtil.string2PrivateKey(KeyUtil.SERVER_PRIVATE_KEY);
		//用Server私钥解密AES秘钥
		byte[] aesKeyBytes = ECCUtil.privateDecrypt(AESUtil.base642Byte(encryptAesKeyStr), serverPrivateKey);
		//用AES秘钥解密APP公钥
		SecretKey aesKey = AESUtil.loadKeyAES(new String(aesKeyBytes));
		byte[] appPublicKeyBytes = AESUtil.decryptAES(AESUtil.base642Byte(encryptAppPublicKeyStr), aesKey);
		//用AES秘钥解密请求内容
		byte[] request = AESUtil.decryptAES(AESUtil.base642Byte(encryptContent), aesKey);
		
		JSONObject result2 = new JSONObject();
		result2.put("ak", new String(aesKeyBytes));
		result2.put("apk", new String(appPublicKeyBytes));
		result2.put("ct", new String(request));
		return result2.toString();
	}
}


测试类 TestHttpEncrypt:

package com.zhuyun.encrypt;

import java.io.InputStream;
import java.security.KeyPair;
import java.util.Properties;

import org.junit.Test;

public class TestHttpEncrypt {

	@Test
	public void testGenerateKeyPair() throws Exception{
		//生成RSA公钥和私钥,并Base64编码
//		KeyPair keyPair = RSAUtil.getKeyPair();
//		String publicKeyStr = RSAUtil.getPublicKey(keyPair);
//		String privateKeyStr = RSAUtil.getPrivateKey(keyPair);
//		System.out.println("RSA公钥Base64编码:" + publicKeyStr);
//		System.out.println("RSA私钥Base64编码:" + privateKeyStr);
		
		//生成ECC公钥和私钥,并Base64编码
		KeyPair keyPair = ECCUtil.getKeyPair();
		String publicKeyStr = ECCUtil.getPublicKey(keyPair);
		String privateKeyStr = ECCUtil.getPrivateKey(keyPair);
		System.out.println("ECC公钥Base64编码:" + publicKeyStr);
		System.out.println("ECC私钥Base64编码:" + privateKeyStr);
	}
	
	
	@Test
	public void testGenerateAesKey() throws Exception{
		//生成AES秘钥,并Base64编码
		String base64Str = AESUtil.genKeyAES();
		System.out.println("AES秘钥Base64编码:" + base64Str);
	}
	
	//测试  APP加密请求内容
	@Test
	public void testAppEncrypt() throws Exception{
		//APP端公钥和私钥从配置文件读取,不能写死在代码里
		Properties prop = new Properties();
		InputStream in = TestHttpEncrypt.class.getClassLoader().getResourceAsStream("client.properties");
		prop.load(in);
		String appPublicKey = prop.getProperty("app.public.key");
		//请求的实际内容
//		String content = "{\"name\":\"infi\", \"weight\":\"60\"}";
		String content = "{\"tenantid\":\"1\", \"account\":\"13015929018\", \"pwd\":\"123456\"}";
		String result = HttpEncryptUtil.appEncrypt(appPublicKey, content);
		System.out.println(result);
	}
	
	//测试  服务器解密APP的请求内容
	@Test
	public void testServerDecrypt() throws Exception{
		String result = "{\"ak\":\"BPXJhKTtBu6YrFXdxnzzl32tIKMER6X/XfaXbBKKqg6VP0m8Wk2AV+Se+D1MWgqaSC+ahzHh1s8m1hjdbSkFf4eBjdzwSbb0YXDofCgrD0fxvbQQsQdVhSRiL/nPlLzrgtQ9yGAcCF4qjDa4dA==\",\"apk\":\"Dtz7R4XbboA/SwsrUDXXEgt6q3fmMTqh4kvxZA1UyMvhi4isEgKoDL6KuLixXGXI709PBBW22kK6hz1jgMWUAr7QBUA8EqdLsi5GFPukEKBS1b+Xh71KKnwY21+uppds8gsJ9cPbxPmduJoCq44fwn15entZQ9EaWN+2xisF4ac=\",\"ct\":\"CAqCFSHCMKFKpEECVBngMX8sGD2teaeyLiQ13X4b2+gkOrm/mYnzvWpPK/tpQNWThw2146VcXrQX+NZNEOH5Vw==\"}";
		System.out.println(HttpEncryptUtil.serverDecrypt(result));
	}
	
	//测试 服务器加密响应给APP的内容
	@Test
	public void testserverEncrypt() throws Exception{
		String aesKeyStr = "zQMfufsgoWP+FWCKteGjdg==";
		String appPublicKeyStr = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFXblKT9aq5X86K+d5RzXpspH4GVwqbSkUc80EbkJn7+ZIejEWba/Io9c5DftUy0AiGXlz9/HgFPdhYBuz5p5rg==";
		String content = "{\"retcode\":\"200\"}";
		System.out.println(HttpEncryptUtil.serverEncrypt(appPublicKeyStr, aesKeyStr, content));
	}
	
	//测试 	APP解密服务器的响应内容
	@Test
	public void testAppDecrypt() throws Exception{
		//APP端公钥和私钥从配置文件读取,不能写死在代码里
		Properties prop = new Properties();
		InputStream in = TestHttpEncrypt.class.getClassLoader().getResourceAsStream("client.properties");
		prop.load(in);
		String appPrivateKey = prop.getProperty("app.private.key");
		String content = "{\"ak\":\"BArM6HfwUYj78sSXrhzYDjVjjpl6Gp3UiFYvNXCJMKfk6aQnC9vto6ZniCEyWAEhmaw9xOw5GmyUy17tV8tiYwKGFfDhS1c4oGOsPEG9KiOxIOuo2saTwrTCGvCwDNju3AGJGfGg8SbnXBndkA==\",\"ct\":\"xE/BBpt30aS/fE5OMJGsyKOcqwlN9MT1swcqbiuMuLnZw98wwGCSZ0aeCdJkDkaZ/JfcJc3exf0tA+/UNdPZ8a7khq5RYyZNA1VfHdhKq6n6n7f7xDqHVZ7uW7ljeLRm\"}";
		System.out.println(HttpEncryptUtil.appDecrypt(appPrivateKey, content));
	}
}



  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 26
    评论
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值