diff --git a/pom.xml b/pom.xml index c24398c..d8c0e7e 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,19 @@ UTF-8 + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + + + + junit @@ -39,5 +52,43 @@ fastjson 1.2.7 + + com.squareup.okhttp3 + okhttp + 3.10.0 + + + com.google.code.gson + gson + 2.8.5 + + + org.springframework + spring-context + 4.3.14.RELEASE + + + org.projectlombok + lombok + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.spring4all + swagger-spring-boot-starter + 1.8.0.RELEASE + diff --git a/src/main/java/com/wustrive/Main.java b/src/main/java/com/wustrive/Main.java index 7066a6a..b2c0084 100644 --- a/src/main/java/com/wustrive/Main.java +++ b/src/main/java/com/wustrive/Main.java @@ -27,7 +27,10 @@ public class Main { "HuGWTIUfItQfSFdjDrEBBuPMFGZtdwJAV5N3xyyIjfMJM4AfKYhpN333HrOvhHX1" + "xVnsHOew8lGKnvMy9Gx11+xPISN/QYMa24dQQo5OAm0TOXwbsF73MwJAHzqaKZPs" + "EN08JunWDOKs3ZS+92maJIm1YGdYf5ipB8/Bm3wElnJsCiAeRqYKmPpAMlCZ5x+Z" + - "AsuC1sjcp2r7xw=="; + "AsuC1sjcp2r7xw==" + + + ; public static final String clientPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmzaI2K/Cpaig/8gjne0F7t3uE" + "7Kx3eLM914A2FhGWYGKiI1Q3KXJ5c7cKJoIzI/cUsXacgnPORjhmtJb2tXzWaRui" + diff --git a/src/main/java/com/wustrive/aesrsa/util/AES.java b/src/main/java/com/wustrive/aesrsa/util/AES.java index 4645e5d..38a590d 100644 --- a/src/main/java/com/wustrive/aesrsa/util/AES.java +++ b/src/main/java/com/wustrive/aesrsa/util/AES.java @@ -1,14 +1,13 @@ package com.wustrive.aesrsa.util; -import java.io.UnsupportedEncodingException; -import java.security.Key; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.security.Key; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; /** * Description: diff --git a/src/main/java/com/wustrive/aesrsa/util/AESRSAUtils.java b/src/main/java/com/wustrive/aesrsa/util/AESRSAUtils.java new file mode 100644 index 0000000..2f30e57 --- /dev/null +++ b/src/main/java/com/wustrive/aesrsa/util/AESRSAUtils.java @@ -0,0 +1,132 @@ +package com.wustrive.aesrsa.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import okhttp3.FormBody; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.*; + +public class AESRSAUtils { +// private static String serverPublicKey=null; + private static String clientPublicKey=null; + private static String clientPrivateKey=null; + private static OkHttpConfig okHttpConfig; + private static Map serverPublicKeys; + + static{ + Properties properties = new Properties(); + try { + properties.load(AESRSAUtils.class.getClassLoader().getResourceAsStream("RSAKeys.properties")); + } catch (IOException e) { + e.printStackTrace(); + } + serverPublicKeys=new HashMap(); + if(properties.getProperty("serverHosts")!=null && !properties.getProperty("serverHosts").isEmpty()){ + String[] serverHosts=properties.getProperty("serverHosts").split(" "); + for(int hostIndex=0;hostIndex map= RSA.generateKeyPair(); + clientPrivateKey = map.get("privateKey"); + clientPublicKey = map.get("publicKey"); + } catch (Exception e) { + e.printStackTrace(); + } + } + okHttpConfig=new OkHttpConfig(); + } + + public static String sendMessage(String url,T t) throws Exception{ + String json = GsonUtils.getJsonByObject(t); + TreeMap params = new TreeMap(); + params.put("data",json); + params.put("publicKey",clientPublicKey); + String sign = EncryUtil.handleRSA(params,clientPrivateKey); + params.put("sign",sign); + + String info= JSON.toJSONString(params); + String aesKey = SecureRandomUtil.getRandom(16); + String data = AES.encryptToBase64(ConvertUtils.stringToHexString(info),aesKey); + + String encryptkey = RSA.encrypt(aesKey,serverPublicKeys.get(new URL(url).getHost())); + + FormBody formBody=new FormBody.Builder().add("data",data).build(); + Request request=new Request.Builder().url(url).addHeader("aesKey",encryptkey).post(formBody).build(); + + String returnData=""; + OkHttpClient okHttpClient=okHttpConfig.okHttpClient(); + Response response = okHttpClient.newCall(request).execute(); + return response.body().string(); + } + + + public static T decryptMessage(String ciphertext,String encryptkey,String host,Class clz) throws Exception{ + String serverPublicKey = serverPublicKeys.get(host); + if(serverPublicKey == null){ + String tmpAESKey=RSA.decrypt(encryptkey,clientPrivateKey); + String tmpInfo=ConvertUtils.hexStringToString(AES.decryptFromBase64(ciphertext,tmpAESKey)); + JSONObject tmpJSONObject= JSON.parseObject(tmpInfo); + serverPublicKey = tmpJSONObject.getString("publicKey"); + } + boolean passSign = EncryUtil.checkDecryptAndSign(ciphertext,encryptkey,serverPublicKey,clientPrivateKey); + if(passSign){ + String aesKey = RSA.decrypt(encryptkey,clientPrivateKey); + String data = ConvertUtils.hexStringToString(AES.decryptFromBase64(ciphertext,aesKey)); + + JSONObject jsonObject = JSONObject.parseObject(data); + String json = jsonObject.getString("data"); +// storeProperties(); + return GsonUtils.getObjectByJson(json,clz); + }else { + serverPublicKeys.put(host,null); + } + + + + return null; + } + + private static void storeProperties(){ + Properties properties = new Properties(); + properties.setProperty("privateKey",clientPrivateKey); + properties.setProperty("publicKey",clientPublicKey); + String serverHosts=""; + int hostIndex=0; + for(Map.Entry entry:serverPublicKeys.entrySet()){ + if(entry.getValue() != null){ + serverHosts += entry.getKey()+" "; + properties.setProperty("serverPublicKey."+(++hostIndex),entry.getValue()); + } + } + properties.setProperty("serverHosts",serverHosts); + + FileOutputStream fileOutputStream = null; + try { + fileOutputStream = new FileOutputStream(AESRSAUtils.class.getClassLoader().getResource("RSAKeys.properties").getPath()); + properties.store(fileOutputStream,new Date().toString()); + fileOutputStream.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/wustrive/aesrsa/util/Base64.java b/src/main/java/com/wustrive/aesrsa/util/Base64.java index 8626e74..57b8fb2 100644 --- a/src/main/java/com/wustrive/aesrsa/util/Base64.java +++ b/src/main/java/com/wustrive/aesrsa/util/Base64.java @@ -464,7 +464,7 @@ public static String decode(String cryptoStr) throws String result = tempStr.substring(40, tempStr.length()); return new String(decode(result.getBytes("UTF-8"))); } - catch(java.lang.ArrayIndexOutOfBoundsException ex) + catch(ArrayIndexOutOfBoundsException ex) { return ""; } diff --git a/src/main/java/com/wustrive/aesrsa/util/ConvertUtils.java b/src/main/java/com/wustrive/aesrsa/util/ConvertUtils.java index 0da14a9..8e7afd4 100644 --- a/src/main/java/com/wustrive/aesrsa/util/ConvertUtils.java +++ b/src/main/java/com/wustrive/aesrsa/util/ConvertUtils.java @@ -322,7 +322,7 @@ public static Object getObject(String type,String value) throws Exception{ else{ Object objs[]=new String[]{value}; return Class.forName(type).getConstructor(new Class[] { - java.lang.String.class + String.class }).newInstance(objs); } } diff --git a/src/main/java/com/wustrive/aesrsa/util/Digest.java b/src/main/java/com/wustrive/aesrsa/util/Digest.java index 7f39326..fddfe88 100644 --- a/src/main/java/com/wustrive/aesrsa/util/Digest.java +++ b/src/main/java/com/wustrive/aesrsa/util/Digest.java @@ -1,12 +1,12 @@ package com.wustrive.aesrsa.util; +import org.apache.log4j.Logger; + import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; -import org.apache.log4j.Logger; - public class Digest { private static final Logger log = Logger.getLogger(Digest.class); public static final String ENCODE = "UTF-8"; diff --git a/src/main/java/com/wustrive/aesrsa/util/EncryUtil.java b/src/main/java/com/wustrive/aesrsa/util/EncryUtil.java index 773a58f..5b7065d 100644 --- a/src/main/java/com/wustrive/aesrsa/util/EncryUtil.java +++ b/src/main/java/com/wustrive/aesrsa/util/EncryUtil.java @@ -1,15 +1,13 @@ package com.wustrive.aesrsa.util; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.TypeReference; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.TypeReference; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.TreeMap; public class EncryUtil { private static final Logger log = Logger.getLogger(EncryUtil.class); @@ -19,7 +17,7 @@ public class EncryUtil { public static String handleRSA(TreeMap map, String privateKey) { StringBuffer sbuffer = new StringBuffer(); - for (Map.Entry entry : map.entrySet()) { + for (Entry entry : map.entrySet()) { sbuffer.append(entry.getValue()); } String signTemp = sbuffer.toString(); @@ -33,7 +31,7 @@ public static String handleRSA(TreeMap map, /** * 返回的结果进行验签 - * + * * @param data * 业务数据密文 * @param encrypt_key @@ -61,7 +59,7 @@ public static boolean checkDecryptAndSign(String data, String encrypt_key, /** 2.用aeskey解开data。取得data明文 */ String realData = ConvertUtils.hexStringToString(AES.decryptFromBase64(data, AESKey)); - + TreeMap map = JSON.parseObject(realData, new TypeReference>() {}); @@ -80,7 +78,7 @@ public static boolean checkDecryptAndSign(String data, String encrypt_key, } signData.append(entry.getValue() == null ? "" : entry.getValue()); } - + /** 5. result为true时表明验签通过 */ boolean result = RSA.checkSign(signData.toString(), sign, clientPublicKey); @@ -93,7 +91,7 @@ public static boolean checkDecryptAndSign(String data, String encrypt_key, */ public static String handleHmac(TreeMap map, String hmacKey) { StringBuffer sbuffer = new StringBuffer(); - for (Map.Entry entry : map.entrySet()) { + for (Entry entry : map.entrySet()) { sbuffer.append(entry.getValue()); } String hmacTemp = sbuffer.toString(); diff --git a/src/main/java/com/wustrive/aesrsa/util/GsonUtils.java b/src/main/java/com/wustrive/aesrsa/util/GsonUtils.java new file mode 100644 index 0000000..bd3bbca --- /dev/null +++ b/src/main/java/com/wustrive/aesrsa/util/GsonUtils.java @@ -0,0 +1,22 @@ +package com.wustrive.aesrsa.util; + +import com.google.gson.Gson; + +public class GsonUtils { + private static Gson gson=null; + + private static Gson getGson(){ + if(gson==null){ + gson = new Gson(); + } + return gson; + } + + public static T getObjectByJson(String json,Class clz){ + return getGson().fromJson(json,clz); + } + + public static String getJsonByObject(T t){ + return getGson().toJson(t); + } +} diff --git a/src/main/java/com/wustrive/aesrsa/util/OkHttpConfig.java b/src/main/java/com/wustrive/aesrsa/util/OkHttpConfig.java new file mode 100644 index 0000000..4a8912f --- /dev/null +++ b/src/main/java/com/wustrive/aesrsa/util/OkHttpConfig.java @@ -0,0 +1,73 @@ +package com.wustrive.aesrsa.util; + +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.concurrent.TimeUnit; + +@Configuration +public class OkHttpConfig { + + @Bean + public OkHttpClient okHttpClient() { + return new OkHttpClient.Builder() + //.sslSocketFactory(sslSocketFactory(), x509TrustManager()) + .retryOnConnectionFailure(true) + .connectionPool(pool()) + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .build(); + } + + @Bean + public X509TrustManager x509TrustManager() { + return new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }; + } + + @Bean + public SSLSocketFactory sslSocketFactory() { + try { + //信任任何链接 + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom()); + return sslContext.getSocketFactory(); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + e.printStackTrace(); + } + return null; + } + + /** + * Create a new connection pool with tuning parameters appropriate for a single-user application. + * The tuning parameters in this pool are subject to change in future OkHttp releases. Currently + */ + @Bean + public ConnectionPool pool() { + return new ConnectionPool(200, 5, TimeUnit.MINUTES); + } +} diff --git a/src/main/java/com/wustrive/aesrsa/util/RSA.java b/src/main/java/com/wustrive/aesrsa/util/RSA.java index 22f6d36..0d1fe08 100644 --- a/src/main/java/com/wustrive/aesrsa/util/RSA.java +++ b/src/main/java/com/wustrive/aesrsa/util/RSA.java @@ -23,25 +23,18 @@ --------------------------------------------**********-------------------------------------------- */ + +import org.apache.log4j.Logger; + +import javax.crypto.Cipher; import java.math.BigInteger; -import java.security.Key; -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.Signature; +import java.security.*; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; -import javax.crypto.Cipher; - -import org.apache.log4j.Logger; - public class RSA { private static final Logger log = Logger.getLogger(RSA.class); /** 指定key的大小 */ @@ -174,7 +167,7 @@ public static boolean checkSign(String content, String sign, String publicKey) PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); - java.security.Signature signature = java.security.Signature + Signature signature = Signature .getInstance("SHA256WithRSA"); signature.initVerify(pubKey); diff --git a/src/main/resources/RSAKeys.properties b/src/main/resources/RSAKeys.properties new file mode 100644 index 0000000..1141150 --- /dev/null +++ b/src/main/resources/RSAKeys.properties @@ -0,0 +1,10 @@ +#clientPrivateKey=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKbNojYr8KlqKD/yCOd7QXu3e4TsrHd4sz3XgDYWEZZgYqIjVDcpcnlztwomgjMj9xSxdpyCc85GOGa0lva1fNZpG6KXYS1xuFa9G7FRbaACoCL31TRv8t4TNkfQhQ7e2S7ZktqyUePWYLlzu8hx5jXdriErRIx1jWK1q1NeEd3NAgMBAAECgYAws7Ob+4JeBLfRy9pbs/ovpCf1bKEClQRIlyZBJHpoHKZPzt7k6D4bRfT4irvTMLoQmawXEGO9o3UOT8YQLHdRLitW1CYKLy8k8ycyNpB/1L2vP+kHDzmM6Pr0IvkFgnbIFQmXeS5NBV+xOdlAYzuPFkCyfUSOKdmt3F/Pbf9EhQJBANrF5Uaxmk7qGXfRV7tCT+f27eAWtYi2h/gJenLrmtkeHg7SkgDiYHErJDns85va4cnhaAzAI1eSIHVaXh3JGXcCQQDDL9ns78LNDr/QuHN9pmeDdlQfikeDKzW8dMcUIqGVX4WQJMptviZuf3cMvgm9+hDTVLvSePdTlA9YSCF4VNPbAkEAvbe54XlpCKBIX7iiLRkPdGiV1qu614j7FqUZlAkvKrPMeywuQygNXHZ+HuGWTIUfItQfSFdjDrEBBuPMFGZtdwJAV5N3xyyIjfMJM4AfKYhpN333HrOvhHX1xVnsHOew8lGKnvMy9Gx11+xPISN/QYMa24dQQo5OAm0TOXwbsF73MwJAHzqaKZPsEN08JunWDOKs3ZS+92maJIm1YGdYf5ipB8/Bm3wElnJsCiAeRqYKmPpAMlCZ5x+ZAsuC1sjcp2r7xw== +#clientPublicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmzaI2K/Cpaig/8gjne0F7t3uE7Kx3eLM914A2FhGWYGKiI1Q3KXJ5c7cKJoIzI/cUsXacgnPORjhmtJb2tXzWaRuil2EtcbhWvRuxUW2gAqAi99U0b/LeEzZH0IUO3tku2ZLaslHj1mC5c7vIceY13a4hK0SMdY1itatTXhHdzQIDAQAB + +#ͻãɾ +serverHosts=172.17.12.23 +serverPublicKey.1=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyGffCqoC1vCDLeBvjfuHdw4johGvubOpQjEhhPzW1PbLSRKsNBLgj+eDGOiZE9BwmEwqy16sMOq0kMlhewTQlRrLJNlw3L0iogs9WTIGm3el1SuZLyMnMksnV0NCsuq538cPMNppZRwARb7NXmpmh0KM79fJ/1xqnpo1tgRcv4wIDAQAB + +#ãͻɾ +privateKey=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALIZ98KqgLW8IMt4G+N+4d3DiOiEa+5s6lCMSGE/NbU9stJEqw0EuCP54MY6JkT0HCYTCrLXqww6rSQyWF7BNCVGssk2XDcvSKiCz1ZMgabd6XVK5kvIycySydXQ0Ky6rnfxw8w2mllHABFvs1eamaHQozv18n/XGqemjW2BFy/jAgMBAAECgYAxT3FCi3SBXKnzy7hk/z9H6Bhi0C8V3z/stzpe+mJDYOa+wtZdD15wT4HFQFpSIwgcHo+Kvp2UEDbZ27qN2Y43AZbF9LOalWTRUzYtr8wL8MIbgtew/QQ9YFNWdkTZ6MxCItjD/mSz3Lrkcphvbsx4VoCVYIJ04r+Loi0t9g0guQJBANvkpfrq0bLVRYWfaigjkx47mr0trJkB7mjADe69IqtsM/2x5dHPpClDK78yzAWxU2BrYzOd31QIOm32iMIvRxUCQQDPWJPMOzcq8Jqs1PAM7D0hxnvF3tSJB0CJCQWdGFkJiuIYSbrWnCVF78jJyU2AK1H3RDi9BzGPL2Z3i2Si+9kXAkAPnKtAJl3fEY9PDmNuGCCA3AB/f/eqIV345/HVSm5kt1j1oSTNAa4JE/DOMWAU42MlDFrNtl69y5vCZOeOyeaFAkBOJieGmWcAozDZJWTYqg2cdk/eU08t2nLjc2gPPscIRrVSzC9EhhOyWV8HVv0D6s/471inPlfajNYFBp/Goj+/AkEAiejHX/58Vv8+ccW22RMZmyxiHcZpTw9hz7vHUCWv03+fyVGtGMhJ4xuPt8UaZm91yHSPWWarM8Xa7errKaXN9A== +publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyGffCqoC1vCDLeBvjfuHdw4johGvubOpQjEhhPzW1PbLSRKsNBLgj+eDGOiZE9BwmEwqy16sMOq0kMlhewTQlRrLJNlw3L0iogs9WTIGm3el1SuZLyMnMksnV0NCsuq538cPMNppZRwARb7NXmpmh0KM79fJ/1xqnpo1tgRcv4wIDAQAB \ No newline at end of file