十次方社交项目-接口加密4
一、搭建接口加密微服务
接口加解密请求参数的流程

二、创建tensquare_encrypt网关服务
在tensquare_parent父工程下新建tensquare_encrypt子模块,并按下面的步骤添加配置和代码
1. 在pom.xml文件中添加以下配置
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>tensquare_parent</artifactId> <groupId>com.tensquare</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>tensquare_encrypt</artifactId> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> <version>2.1.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> <version>2.1.1.RELEASE</version> </dependency> </dependencies> </project>
2. 在resource文件夹下新建application.yml文件,并添加如下配置
server:
port: 9013
spring:
application:
name: tensquare-encrypt
zuul:
routes:
tensquare-article: #路由到文章微服务
path: /article/** #配置请求URL的请求规则
serviceId: tensquare-article #指定Eureka注册中心的服务id
strip-prefix: true #所有的article请求都进行转发
sentiviteHeaders:
customSensitiveHeaders: true #让zuul网关处理Cookeie和重定向
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:6868/eureka/
instance:
prefer-ip-address: true
3. 新建com.tensquare.encrypt包,并在包下新建启动类EncryptApplication,添加如下代码
package com.tensquare.encrypt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class EncryptApplication {
public static void main(String[] args) {
SpringApplication.run(EncryptApplication.class,args);
}
}
4. 将rsa相关的工具类复制到在com.tensquare.encrypt包下
工具类的位置放在rsa和service文件夹下

Base64Utils
package com.tensquare.encrypt.rsa; import java.io.*; public class Base64Utils { /** */ /** * 28. * 文件读取缓冲区大小 * 29. */ private static final int CACHE_SIZE = 1024; /** */ /** * 33. * <p> * 34. * BASE64字符串解码为二进制数据 * 35. * </p> * 36. * * 37. * @param base64 * 38. * @return * 39. * @throws Exception * 40. */ public static byte[] decode(String base64) throws Exception { return mBase64.decode(base64.getBytes()); } /** */ /** * 46. * <p> * 47. * 二进制数据编码为BASE64字符串 * 48. * </p> * 49. * * 50. * @param bytes * 51. * @return * 52. * @throws Exception * 53. */ public static String encode(byte[] bytes) throws Exception { return new String(mBase64.encode(bytes)); } /** */ /** * 59. * <p> * 60. * 将文件编码为BASE64字符串 * 61. * </p> * 62. * <p> * 63. * 大文件慎用,可能会导致内存溢出 * 64. * </p> * 65. * * 66. * @param filePath 文件绝对路径 * 67. * @return * 68. * @throws Exception * 69. */ public static String encodeFile(String filePath) throws Exception { byte[] bytes = fileToByte(filePath); return encode(bytes); } /** */ /** * 76. * <p> * 77. * BASE64字符串转回文件 * 78. * </p> * 79. * * 80. * @param filePath 文件绝对路径 * 81. * @param base64 编码字符串 * 82. * @throws Exception * 83. */ public static void decodeToFile(String filePath, String base64) throws Exception { byte[] bytes = decode(base64); byteArrayToFile(bytes, filePath); } /** */ /** * <p> * 文件转换为二进制数组 * </p> * * @param filePath 文件路径 * @return * @throws Exception */ public static byte[] fileToByte(String filePath) throws Exception { byte[] data = new byte[0]; File file = new File(filePath); if (file.exists()) { FileInputStream in = new FileInputStream(file); ByteArrayOutputStream out = new ByteArrayOutputStream(2048); byte[] cache = new byte[CACHE_SIZE]; int nRead = 0; while ((nRead = in.read(cache)) != -1) { out.write(cache, 0, nRead); out.flush(); } out.close(); in.close(); data = out.toByteArray(); } return data; } /** */ /** * 118. * <p> * 119. * 二进制数据写文件 * 120. * </p> * 121. * * 122. * @param bytes 二进制数据 * 123. * @param filePath 文件生成目录 * 124. */ public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception { InputStream in = new ByteArrayInputStream(bytes); File destFile = new File(filePath); if (!destFile.getParentFile().exists()) { destFile.getParentFile().mkdirs(); } destFile.createNewFile(); OutputStream out = new FileOutputStream(destFile); byte[] cache = new byte[CACHE_SIZE]; int nRead = 0; while ((nRead = in.read(cache)) != -1) { out.write(cache, 0, nRead); out.flush(); } out.close(); in.close(); } //新增----------------------------------------- private static char[] base64EncodeChars = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',}; private static byte[] base64DecodeChars = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1}; /** * 解密 * * @param data * @return */ public static byte[] decodeStr(byte[] data) { // byte[] data = str.getBytes(); int len = data.length; ByteArrayOutputStream buf = new ByteArrayOutputStream(len); int i = 0; int b1, b2, b3, b4; while (i < len) { do { b1 = base64DecodeChars[data[i++]]; } while (i < len && b1 == -1); if (b1 == -1) { break; } do { b2 = base64DecodeChars[data[i++]]; } while (i < len && b2 == -1); if (b2 == -1) { break; } buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4))); do { b3 = data[i++]; if (b3 == 61) { return buf.toByteArray(); } b3 = base64DecodeChars[b3]; } while (i < len && b3 == -1); if (b3 == -1) { break; } buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); do { b4 = data[i++]; if (b4 == 61) { return buf.toByteArray(); } b4 = base64DecodeChars[b4]; } while (i < len && b4 == -1); if (b4 == -1) { break; } buf.write((int) (((b3 & 0x03) << 6) | b4)); } return buf.toByteArray(); } }
mBase64
package com.tensquare.encrypt.rsa; /** * Created by Administrator on 2017/10/30. */ public class mBase64 { static final int CHUNK_SIZE = 76; static final byte[] CHUNK_SEPARATOR = "\r\n".getBytes(); private static final int BASELENGTH = 255; private static final int LOOKUPLENGTH = 64; private static final int EIGHTBIT = 8; private static final int SIXTEENBIT = 16; private static final int TWENTYFOURBITGROUP = 24; private static final int FOURBYTE = 4; private static final int SIGN = -128; private static final byte PAD = 61; private static final byte[] base64Alphabet = new byte[255]; private static final byte[] lookUpBase64Alphabet = new byte[64]; public mBase64() { } private static boolean isBase64(byte octect) { return octect == 61 ? true : octect >= 0 && base64Alphabet[octect] != -1; } public static boolean isBase64(byte[] arrayOctect) { arrayOctect = discardWhitespace(arrayOctect); int length = arrayOctect.length; if (length == 0) { return true; } else { for (int i = 0; i < length; ++i) { if (!isBase64(arrayOctect[i])) { return false; } } return true; } } static byte[] discardWhitespace(byte[] data) { byte[] groomedData = new byte[data.length]; int bytesCopied = 0; byte[] packedData = data; int len$ = data.length; int i$ = 0; while (i$ < len$) { byte aByte = packedData[i$]; switch (aByte) { default: groomedData[bytesCopied++] = aByte; case 9: case 10: case 13: case 32: ++i$; } } packedData = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } // public static String encodeToString(byte[] bytes) { // byte[] encoded = encode(bytes); // return CodecSupport.toString(encoded); // } public static byte[] encodeChunked(byte[] binaryData) { return encode(binaryData, true); } public static byte[] encode(byte[] pArray) { return encode(pArray, false); } public static byte[] encode(byte[] binaryData, boolean isChunked) { long binaryDataLength = (long) binaryData.length; long lengthDataBits = binaryDataLength * 8L; long fewerThan24bits = lengthDataBits % 24L; long tripletCount = lengthDataBits / 24L; int chunckCount = 0; long encodedDataLengthLong; if (fewerThan24bits != 0L) { encodedDataLengthLong = (tripletCount + 1L) * 4L; } else { encodedDataLengthLong = tripletCount * 4L; } if (isChunked) { chunckCount = CHUNK_SEPARATOR.length == 0 ? 0 : (int) Math.ceil((double) ((float) encodedDataLengthLong / 76.0F)); encodedDataLengthLong += (long) (chunckCount * CHUNK_SEPARATOR.length); } if (encodedDataLengthLong > 2147483647L) { throw new IllegalArgumentException("Input array too big, output array would be bigger than Integer.MAX_VALUE=2147483647"); } else { int encodedDataLength = (int) encodedDataLengthLong; byte[] encodedData = new byte[encodedDataLength]; int encodedIndex = 0; int nextSeparatorIndex = 76; int chunksSoFar = 0; byte k; byte l; byte b1; byte b2; int dataIndex; int i; byte val1; byte val2; for (i = 0; (long) i < tripletCount; ++i) { dataIndex = i * 3; b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; byte b3 = binaryData[dataIndex + 2]; l = (byte) (b2 & 15); k = (byte) (b1 & 3); val1 = (b1 & -128) == 0 ? (byte) (b1 >> 2) : (byte) (b1 >> 2 ^ 192); val2 = (b2 & -128) == 0 ? (byte) (b2 >> 4) : (byte) (b2 >> 4 ^ 240); byte val3 = (b3 & -128) == 0 ? (byte) (b3 >> 6) : (byte) (b3 >> 6 ^ 252); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | k << 4]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2 | val3]; encodedData[encodedIndex + 3] = lookUpBase64Alphabet[b3 & 63]; encodedIndex += 4; if (isChunked && encodedIndex == nextSeparatorIndex) { System.arraycopy(CHUNK_SEPARATOR, 0, encodedData, encodedIndex, CHUNK_SEPARATOR.length); ++chunksSoFar; nextSeparatorIndex = 76 * (chunksSoFar + 1) + chunksSoFar * CHUNK_SEPARATOR.length; encodedIndex += CHUNK_SEPARATOR.length; } } dataIndex = i * 3; if (fewerThan24bits == 8L) { b1 = binaryData[dataIndex]; k = (byte) (b1 & 3); val1 = (b1 & -128) == 0 ? (byte) (b1 >> 2) : (byte) (b1 >> 2 ^ 192); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[k << 4]; encodedData[encodedIndex + 2] = 61; encodedData[encodedIndex + 3] = 61; } else if (fewerThan24bits == 16L) { b1 = binaryData[dataIndex]; b2 = binaryData[dataIndex + 1]; l = (byte) (b2 & 15); k = (byte) (b1 & 3); val1 = (b1 & -128) == 0 ? (byte) (b1 >> 2) : (byte) (b1 >> 2 ^ 192); val2 = (b2 & -128) == 0 ? (byte) (b2 >> 4) : (byte) (b2 >> 4 ^ 240); encodedData[encodedIndex] = lookUpBase64Alphabet[val1]; encodedData[encodedIndex + 1] = lookUpBase64Alphabet[val2 | k << 4]; encodedData[encodedIndex + 2] = lookUpBase64Alphabet[l << 2]; encodedData[encodedIndex + 3] = 61; } if (isChunked && chunksSoFar < chunckCount) { System.arraycopy(CHUNK_SEPARATOR, 0, encodedData, encodedDataLength - CHUNK_SEPARATOR.length, CHUNK_SEPARATOR.length); } return encodedData; } } // public static String decodeToString(String base64Encoded) { // byte[] encodedBytes = CodecSupport.toBytes(base64Encoded); // return decodeToString(encodedBytes); // } // // public static String decodeToString(byte[] base64Encoded) { // byte[] decoded = decode(base64Encoded); // return CodecSupport.toString(decoded); // } // // public static byte[] decode(String base64Encoded) { // byte[] bytes = CodecSupport.toBytes(base64Encoded); // return decode(bytes); // } public static byte[] decode(byte[] base64Data) { base64Data = discardNonBase64(base64Data); if (base64Data.length == 0) { return new byte[0]; } else { int numberQuadruple = base64Data.length / 4; int encodedIndex = 0; int i = base64Data.length; while (base64Data[i - 1] == 61) { --i; if (i == 0) { return new byte[0]; } } byte[] decodedData = new byte[i - numberQuadruple]; for (i = 0; i < numberQuadruple; ++i) { int dataIndex = i * 4; byte marker0 = base64Data[dataIndex + 2]; byte marker1 = base64Data[dataIndex + 3]; byte b1 = base64Alphabet[base64Data[dataIndex]]; byte b2 = base64Alphabet[base64Data[dataIndex + 1]]; byte b3; if (marker0 != 61 && marker1 != 61) { b3 = base64Alphabet[marker0]; byte b4 = base64Alphabet[marker1]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) ((b2 & 15) << 4 | b3 >> 2 & 15); decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); } else if (marker0 == 61) { decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); } else { b3 = base64Alphabet[marker0]; decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); decodedData[encodedIndex + 1] = (byte) ((b2 & 15) << 4 | b3 >> 2 & 15); } encodedIndex += 3; } return decodedData; } } static byte[] discardNonBase64(byte[] data) { byte[] groomedData = new byte[data.length]; int bytesCopied = 0; byte[] packedData = data; int len$ = data.length; for (int i$ = 0; i$ < len$; ++i$) { byte aByte = packedData[i$]; if (isBase64(aByte)) { groomedData[bytesCopied++] = aByte; } } packedData = new byte[bytesCopied]; System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); return packedData; } static { int i; for (i = 0; i < 255; ++i) { base64Alphabet[i] = -1; } for (i = 90; i >= 65; --i) { base64Alphabet[i] = (byte) (i - 65); } for (i = 122; i >= 97; --i) { base64Alphabet[i] = (byte) (i - 97 + 26); } for (i = 57; i >= 48; --i) { base64Alphabet[i] = (byte) (i - 48 + 52); } base64Alphabet[43] = 62; base64Alphabet[47] = 63; for (i = 0; i <= 25; ++i) { lookUpBase64Alphabet[i] = (byte) (65 + i); } i = 26; int j; for (j = 0; i <= 51; ++j) { lookUpBase64Alphabet[i] = (byte) (97 + j); ++i; } i = 52; for (j = 0; i <= 61; ++j) { lookUpBase64Alphabet[i] = (byte) (48 + j); ++i; } lookUpBase64Alphabet[62] = 43; lookUpBase64Alphabet[63] = 47; } }
RSA
package com.tensquare.encrypt.rsa; import sun.misc.BASE64Decoder; import javax.crypto.Cipher; import java.io.ByteArrayOutputStream; import java.security.*; 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.Map; public class RSA { /** */ /** * 加密算法RSA */ public static final String KEY_ALGORITHM = "RSA"; /** */ /** * 签名算法 */ public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; /** */ /** * 获取公钥的key */ private static final String PUBLIC_KEY = "RSAPublicKey"; /** */ /** * 获取私钥的key */ private static final String PRIVATE_KEY = "RSAPrivateKey"; /** */ /** * RSA最大加密明文大小 */ //private static final int MAX_ENCRYPT_BLOCK = 117; private static final int MAX_ENCRYPT_BLOCK = 245; /** */ /** * RSA最大解密密文大小 */ //private static final int MAX_DECRYPT_BLOCK = 128; private static final int MAX_DECRYPT_BLOCK = 256; /** */ /** * <p> * 生成密钥对(公钥和私钥) * </p> * * @return * @throws Exception */ public static Map<String, Object> genKeyPair() throws Exception { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM); keyPairGen.initialize(1024); KeyPair keyPair = keyPairGen.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); Map<String, Object> keyMap = new HashMap<String, Object>(2); keyMap.put(PUBLIC_KEY, publicKey); keyMap.put(PRIVATE_KEY, privateKey); return keyMap; } /** */ /** * <p> * 用私钥对信息生成数字签名 * </p> * * @param data 已加密数据 * @param privateKey 私钥(BASE64编码) * @return * @throws Exception */ public static String sign(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(privateK); signature.update(data); return Base64Utils.encode(signature.sign()); } /** */ /** * 112. * <p> * 113. * 校验数字签名 * 114. * </p> * 115. * * 116. * @param data 已加密数据 * 117. * @param publicKey 公钥(BASE64编码) * 118. * @param sign 数字签名 * 119. * * 120. * @return * 121. * @throws Exception * 122. * * 123. */ public static boolean verify(byte[] data, String publicKey, String sign) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); PublicKey publicK = keyFactory.generatePublic(keySpec); Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(publicK); signature.update(data); return signature.verify(Base64Utils.decode(sign)); } /** */ /** * 137. * <P> * 138. * 私钥解密 * 139. * </p> * 140. * * 141. * @param encryptedData 已加密数据 * 142. * @param privateKey 私钥(BASE64编码) * 143. * @return * 144. * @throws Exception * 145. */ public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception { // byte[] keyBytes = Base64Utils.decode(privateKey); // PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = getPrivateKey(privateKey); //Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** * 得到私钥 * * @param key 密钥字符串(经过base64编码) * @throws Exception */ public static PrivateKey getPrivateKey(String key) throws Exception { byte[] keyBytes; keyBytes = (new BASE64Decoder()).decodeBuffer(key); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(keySpec); return privateKey; } /** * 得到公钥 * * @param key 密钥字符串(经过base64编码) * @throws Exception */ public static PublicKey getPublicKey(String key) throws Exception { byte[] keyBytes; keyBytes = (new BASE64Decoder()).decodeBuffer(key); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(keySpec); return publicKey; } /** */ /** * 176. * <p> * 177. * 公钥解密 * 178. * </p> * 179. * * 180. * @param encryptedData 已加密数据 * 181. * @param publicKey 公钥(BASE64编码) * 182. * @return * 183. * @throws Exception * 184. */ public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception { byte[] keyBytes = Base64Utils.decode(publicKey); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicK); int inputLen = encryptedData.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_DECRYPT_BLOCK) { cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK); } else { cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_DECRYPT_BLOCK; } byte[] decryptedData = out.toByteArray(); out.close(); return decryptedData; } /** */ /** * 215. * <p> * 216. * 公钥加密 * 217. * </p> * 218. * * 219. * @param data 源数据 * 220. * @param publicKey 公钥(BASE64编码) * 221. * @return * 222. * @throws Exception * 223. */ public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception { // byte[] keyBytes = Base64Utils.decode(publicKey); // X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicK = getPublicKey(publicKey); // 对数据加密 //Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** */ /** * 255. * <p> * 256. * 私钥加密 * 257. * </p> * 258. * * 259. * @param data 源数据 * 260. * @param privateKey 私钥(BASE64编码) * 261. * @return * 262. * @throws Exception * 263. */ public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception { byte[] keyBytes = Base64Utils.decode(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateK = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateK); int inputLen = data.length; ByteArrayOutputStream out = new ByteArrayOutputStream(); int offSet = 0; byte[] cache; int i = 0; // 对数据分段加密 while (inputLen - offSet > 0) { if (inputLen - offSet > MAX_ENCRYPT_BLOCK) { cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK); } else { cache = cipher.doFinal(data, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * MAX_ENCRYPT_BLOCK; } byte[] encryptedData = out.toByteArray(); out.close(); return encryptedData; } /** */ /** * 294. * <p> * 295. * 获取私钥 * 296. * </p> * 297. * * 298. * @param keyMap 密钥对 * 299. * @return * 300. * @throws Exception */ // public static String getPrivateKey(Map<String, Object> keyMap) // throws Exception { // Key key = (Key) keyMap.get(PRIVATE_KEY); // return Base64Utils.encode(key.getEncoded()); // } /** */ /** * 309. * <p> * 310. * 获取公钥 * 311. * </p> * 312. * * 313. * @param keyMap 密钥对 * 314. * @return * 315. * @throws Exception * 316. */ public static String getPublicKey(Map<String, Object> keyMap) throws Exception { Key key = (Key) keyMap.get(PUBLIC_KEY); return Base64Utils.encode(key.getEncoded()); } }
RsaKeys
package com.tensquare.encrypt.rsa;
/**
* rsa加解密用的公钥和私钥
* @author Administrator
*
*/
public class RsaKeys {
//生成秘钥对的方法可以参考这篇帖子
//https://www.cnblogs.com/yucy/p/8962823.html
//服务器公钥
private static final String serverPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuJ8CmuTbp3iNAtSWTeYa" +
"DqA8WwqeCNfEnbCPOUYRn3JoqxMUxUF1GoDOFTNoBJl2VQJa6u80ovf9OYiNlwgb" +
"Gf+h744kF7cY2c2MroS+gbav4Gf6pyy7W4EbxRcqzzqNcrAfFmQGh7uaIRB5KzI7" +
"PMSk61UT9iNLeBKscn6bNIdbd13S0pXUJrf2yRYtdUYi2ab9uudSOzUSPgXgYAHS" +
"AeF2dnCW3OPQh1TnBUopu+Cy7ficundydVQgWa4US8U4Hwj4wukt0ZZyLuuFygsr" +
"7JwC1ejHtCMY27EOKfHpIiW9/EWPWUg6cTJSCZugVHV/QO5TkibhwxDBX4yWArms" +
"FwIDAQAB";
//服务器私钥(经过pkcs8格式处理)
private static final String serverPrvKeyPkcs8 = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC4nwKa5NuneI0C" +
"1JZN5hoOoDxbCp4I18SdsI85RhGfcmirExTFQXUagM4VM2gEmXZVAlrq7zSi9/05" +
"iI2XCBsZ/6HvjiQXtxjZzYyuhL6Btq/gZ/qnLLtbgRvFFyrPOo1ysB8WZAaHu5oh" +
"EHkrMjs8xKTrVRP2I0t4Eqxyfps0h1t3XdLSldQmt/bJFi11RiLZpv2651I7NRI+" +
"BeBgAdIB4XZ2cJbc49CHVOcFSim74LLt+Jy6d3J1VCBZrhRLxTgfCPjC6S3RlnIu" +
"64XKCyvsnALV6Me0IxjbsQ4p8ekiJb38RY9ZSDpxMlIJm6BUdX9A7lOSJuHDEMFf" +
"jJYCuawXAgMBAAECggEAP6A9S5h3wt2e60zMiAg3DrdWVaHxGOcTkazZj0mApUzO" +
"mba3v8txSjL90vyman9g8qcfIjxSDaAdmwhek6BthqY87swz0CB/5gAa7cI9zYJi" +
"Vpo/HgIih8SVB3WWgViSiuX7sMHEJl8XHTIKMELde3HhzGDDwl4jkjwNRmAvqQgv" +
"M1kvFiWcguDIMswIarbTgSytK2TqhG98rQj5lq2iLDedFu5++mWdeU4n0yp0btCH" +
"IP5nnOkOPv4bjgn0SNokHvHtCQGlT0xQbyWnrE/EY/nettZFbHrCjfpjaM0xtPKl" +
"p0RIoAVsAyEGdPWNYzIulrCpCyvtWUms9iZfv5K3kQKBgQDdqDUcH1R9CtKUCBM+" +
"Kml9M35YHpzrsuElJg/CKTox5UFWp8ZOMELwp9/XevCjxybTfS7TY2H2v9t9bY1j" +
"rzt9ipF2nqEFsEQWiQaKErVAM8RaQedy76codBW0SpQ+z1aHin7c7Hee3uO0x4nt" +
"8fhbyp5Yn2PgIgmniZ76Qa8mCwKBgQDVOc/Yu9yL/W/hbr5NXCTpvxevyb2md1lJ" +
"PJ74vwdcWyvizI/I8pP0ZoXYdnF3V8Fx4xziQtU/xY/pQyjBoG6mr999qlaMRU0x" +
"STNFuwOrhs8mXCNJRBALx8fEMuqpAc80sy06zDpP/LQEW0ESJwKu+rrjziP0lKOP" +
"FMvsbu3VpQKBgAZh1H2lzUn4aM3IWb19fSIUvHuPDhefQ+pM6UE+7KUJI9N56zTP" +
"IO5K9x/+MzWUA2MthI6jmut+5LP81ohbQExCFCQlNx+xzpQTh/OrzDo4A1xR73cY" +
"vWhlx0Y0q4YPdD9c1oBH8r3JTyciY69NO0hxUhPdKwQGFt8TEFfGUmO3AoGAKsl6" +
"EtTH0fOeYs9VMrLd2WX2O9kwzFnAufiHMgUrVfYZnV5NMBa1Z+K20xQZeshKUi8v" +
"2ZttrWlYkodeg1RNP/ek0lO/IFC7x7sXpdN8Tgw0P09X6VjWG3cQeCd7fUSWrs2R" +
"su3OecSM3x7stNbNLA22OQZhoq+9DnYu4Zf0890CgYBgHsYlAHBNkabLGT5GMZg5" +
"Vk2vSEIECY5KUDl2GzUYy3/yJyKGIwySVNDbSS+8VEFJowFXf9unIFymNU61tJ44" +
"c9mF2DL+CzGx3LgmHmfyarlXh5adv9Q6fzVjgtYOgxPS+OeZFWgFVnILC6iqUGRs" +
"NDtB4qh/0XUcjgZGEh3SdQ==";
public static String getServerPubKey() {
return serverPubKey;
}
public static String getServerPrvKeyPkcs8() {
return serverPrvKeyPkcs8;
}
}
RsaService
package com.tensquare.encrypt.service;
/**
*
* @ClassName: RsaService
* @Description: rsa加密解密服务接口
* @author 李建
* @date 2018年6月21日 下午3:27:34
*
*/
public interface RsaService {
/***
* RSA解密
*
* @param encryptData
* @return
* @throws Exception
*/
public String RSADecryptDataPEM(String encryptData, String prvKey) throws Exception;
/***
* RSA解密
*
* @param encryptBytes
* @return
* @throws Exception
*/
public String RSADecryptDataBytes(byte[] encryptBytes, String prvKey) throws Exception;
/***
* RSA加密
*
* @param data
* @return
* @throws Exception
*/
public String RSAEncryptDataPEM(String data, String pubKey) throws Exception;
public String getRsaAlgorithm();
}
RsaServiceImpl
package com.tensquare.encrypt.service;
import com.tensquare.encrypt.rsa.Base64Utils;
import com.tensquare.encrypt.rsa.RSA;
import org.springframework.stereotype.Service;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
/**
* RSA 加解密
*
* @author Administrator
*/
@Service("RsaService")
public class RsaServiceImpl implements RsaService {
/***
* RSA解密
*
* @param encryptData
* @return
* @throws Exception
*/
public String RSADecryptDataPEM(String encryptData, String prvKey) throws Exception {
byte[] encryptBytes = encryptData.getBytes();
byte[] prvdata = RSA.decryptByPrivateKey(Base64Utils.decode(encryptData), prvKey);
String outString = new String(prvdata, "UTF-8");
return outString;
}
@Override
public String RSADecryptDataBytes(byte[] encryptBytes, String prvKey)
throws Exception {
// TODO Auto-generated method stub
byte[] prvdata = RSA.decryptByPrivateKey(encryptBytes, prvKey);
String outString = new String(prvdata, "utf-8");
return outString;
}
/***
* RSA加密
*
* @param data
* @return
* @throws Exception
*/
public String RSAEncryptDataPEM(String data, String pubKey) throws Exception {
byte[] pubdata = RSA.encryptByPublicKey(data.getBytes("UTF-8"), pubKey);
String outString = new String(Base64Utils.encode(pubdata));
return outString;
}
@Override
public String getRsaAlgorithm() {
// TODO Auto-generated method stub
KeyFactory keyFactory = null;
try {
keyFactory = KeyFactory.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return keyFactory.getAlgorithm();
}
}
5. 在src/test/java文件夹下创建测试用例EncryptTest
该测试用例用于将请求参数加密,代码如下
import com.tensquare.encrypt.EncryptApplication;
import com.tensquare.encrypt.rsa.RsaKeys;
import com.tensquare.encrypt.service.RsaService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = EncryptApplication.class)
public class EncryptTest {
@Autowired
private RsaService rsaService;
@Test
public void genEncryptDataByPubKey(){
String data = "{\"title\":\"三十\"}";
try {
String encData = rsaService.RSAEncryptDataPEM(data, RsaKeys.getServerPubKey());
System.out.println("data: "+data);
System.out.println("encData: "+encData);
} catch (Exception e) {
e.printStackTrace();
}
}
}
6. 编写filter
在com.tensquare.encrypt包下新建filters包,然后新建过滤器类RSARequestFilter,添加下面的代码
package com.tensquare.encrypt.filter;
import com.google.common.base.Charsets;
import com.google.common.base.Strings;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import com.tensquare.encrypt.rsa.RsaKeys;
import com.tensquare.encrypt.service.RsaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@Component
public class RSARequestFilter extends ZuulFilter {
@Autowired
private RsaService rsaService;
@Override
public String filterType() {
//过滤器在什么环境执行,解密操作需要在转发之前执行
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//设置过滤器的执行顺序
return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
}
@Override
public boolean shouldFilter() {
//是否使用过滤器,true使用过滤器
return true;
}
@Override
public Object run() throws ZuulException {
//过滤器具体执行的逻辑
System.out.println("过滤器执行了");
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
// HttpServletResponse response = currentContext.getResponse();
try {
String decryptData = null;
HashMap dataMap = null;
String token = null;
String url = request.getRequestURL().toString();
InputStream inputStream = currentContext.getRequest().getInputStream();
String requestParam = StreamUtils.copyToString(inputStream, Charsets.UTF_8);
if(!Strings.isNullOrEmpty(requestParam)){
System.out.println(String.format("请求体中的密文:%s",requestParam));
decryptData = rsaService.RSADecryptDataPEM(requestParam, RsaKeys.getServerPrvKeyPkcs8());
System.out.println(String.format("解密后的内容:%s",decryptData));
}
System.out.println(String.format("request: %s >>> %s,data=%s",request.getMethod(),url,decryptData));
//把解密后的数据进行转发,需要放到request中
//postman请求http://127.0.0.1:9013/article/article/search/1/10转发到article微服务
if(!Strings.isNullOrEmpty(decryptData)){
System.out.println("json字符串写入request body");
final byte[] reqBodyBytes = decryptData.getBytes();
currentContext.setRequest(new HttpServletRequestWrapper(request){
@Override
public ServletInputStream getInputStream() throws IOException{
return new ServletInputStreamWrapper(reqBodyBytes);
}
@Override
public int getContentLength(){
return reqBodyBytes.length;
}
@Override
public long getContentLengthLong(){
return reqBodyBytes.length;
}
});
}
System.out.println("转发request");
currentContext.addZuulRequestHeader("Content-Type",String.valueOf(MediaType.APPLICATION_JSON)+";charset=UTF-8");
} catch (Exception e) {
System.out.println(this.getClass().getName()+"运行出错"+e.getMessage());
}
return null;
}
}
7. 将openssl生成的公钥和私钥添加进RsaKeys中
openssl生成rsa密钥对方法:https://www.cnblogs.com/ajing2018/p/19304617
公钥变量:private static final String serverPubKey
私钥变量:private static final String serverPrvKeyPkcs8
8. 测试请求参数加解密微服务
启动tensquare_eureka,tensquare_article,tensquare_encrypt,使用EncryptTest类加密请求参数,然后使用postman进行接口调用测试
浙公网安备 33010602011771号