java实现双向ECC + AES加密

本文主要是前面《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:

[java] view plain copy

```

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:

[java] view plain copy

```

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));  

    }  

}  

```

你可能感兴趣的:(java实现双向ECC + AES加密)