如何实现接口加密?
为什么要使用接口加密?
系统明文传输的数据会被不明身份的人用抓包工具抓取,从而威胁系统和数据的安全性
我这里采用非对称加密算法:
非对称加密算法是一种密钥的保密方法,加密和解密使用两个不同的密钥,公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。
非对称加密算法的特点:
- 算法强度复杂
- 加密解密速度没有对称密钥算法的速度快
经典应用场景:数字签名(私钥加密,公钥验证)
常用的算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。
1.OpenSSL生成rsa密钥对
密钥长度介于 512 - 65536 之间(JDK 中默认长度是1024),且必须是64 的倍数。密钥的常用文件格式有pem(文本存储)或者der(二进制存储)。
当使用Java API生成RSA密钥对时,公钥以X.509格式编码,私钥以PKCS#8格式编码
RSA使用pkcs协议定义密钥的存储结构等内容。
1.1openssl生成rsa密钥对的命令
openssl genrsa -out …/mycerts/rsa_private_key.pem 2048
生成rsa私钥,文本存储格式,长度2048
openssl rsa -in …/mycerts/rsa_private_key.pem -pubout -out …/mycerts/rsa_public_key_2048.pub
根据私钥生成对应的公钥
openssl pkcs8 -topk8 -inform PEM -in …/mycerts/rsa_private_key.pem -outform PEM -nocrypt > …/mycerts/rsa_private_key_pkcs8.pem
私钥转化成pkcs8格式
业务大概流程:接口调用者把加密后的参数传到zuul网关解密后再访问资源服务
这里需要搭建zuul网关微服务,注册到eureka.服务搭建过程此处省略…
OpenSSl云盘下载:
链接:https://pan.baidu.com/s/1x1qKHDEalTL_36xMJCwnvg
提取码:m02i
复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V2的分享
zuul网关服务结构截图:
package com.baidu.designer.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();
}
}
package com.baidu.designer.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;
}
}
package com.baidu.designer.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());
}
}
package com.baidu.designer.rsa;
/**
* rsa加解密用的公钥和私钥
* @author Mr.Yang
*
*/
public class RsaKeys {
//服务器公钥
private static final String serverPubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtT0/Pmcc5GMYFIwOlxLd\n" +
"Qq9/phM6YUj4bVY25TXfECydYs+1Q/zQp7R6XVE9CDFDbbDe6ogocEqmSj+mEPqI\n" +
"HUL+7xKIsQQU/b2r6PKexOjdh2lcKq/zB/e9WsR6zcuo+knDSg/wEYkCZbEqOY7C\n" +
"Zo5mK8vmLDd6elPytf9nhA5UWXNUzljwT7mmBoBD1QY0uuRF28O/ZdbCcxfM6NG2\n" +
"yNW7bji4jwl9H1HPGqp3Xoip11dJ3NWCXxmOmJAOUFtZU13INZ7aLrgHC+f3XWNp\n" +
"PrFrdNFuJtbUNCeuO08cwfNPNyzYupz9I56rq9QHcWvVbbbMdoQF3hYo7DlWDxZw\n" +
"EQIDAQAB";
//服务器私钥(经过pkcs8格式处理)
private static final String serverPrvKeyPkcs8 = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC1PT8+ZxzkYxgU\n" +
"jA6XEt1Cr3+mEzphSPhtVjblNd8QLJ1iz7VD/NCntHpdUT0IMUNtsN7qiChwSqZK\n" +
"P6YQ+ogdQv7vEoixBBT9vavo8p7E6N2HaVwqr/MH971axHrNy6j6ScNKD/ARiQJl\n" +
"sSo5jsJmjmYry+YsN3p6U/K1/2eEDlRZc1TOWPBPuaYGgEPVBjS65EXbw79l1sJz\n" +
"F8zo0bbI1btuOLiPCX0fUc8aqndeiKnXV0nc1YJfGY6YkA5QW1lTXcg1ntouuAcL\n" +
"5/ddY2k+sWt00W4m1tQ0J647TxzB8083LNi6nP0jnqur1Adxa9Vttsx2hAXeFijs\n" +
"OVYPFnARAgMBAAECggEBAKgDzmR4TLWBE+rAaCovR8UxUuHPw3g6oGsj2KImjdK9\n" +
"uW3H5l/PuFMwIZvu2uiEWuEObaj4bpyi54O/e6ET0CloWVOiV+vaP+d29S5v9TXQ\n" +
"NsX4q4O7N070oKrLqJitq8nTpeI74i8vV3SUh/Nx39AZRKhnTstA5x8OQdvsmLc2\n" +
"zCUrYe1xkaiZ4S3yfX9yhoGeLCNssHhpft2nordFrsyMHDXakJdfRXnPJMjXTn1R\n" +
"7puDvenjwn6MGBjfyXIqXaXNaI+zo5Q3gHZK45/JwSdCvuVKaX3jDqj7IqmuYFKv\n" +
"6o5wjFhEpCxOR+K93vapGj/LsBvMcPFUo/PfBSzCysECgYEA7hT4q5Tnhh6q2d22\n" +
"DQUlAzBdoChvRIqiCA1ScoWrZBgGDjyGbQFubEvyYuDmop75p52JRN5ZPpV4Db5G\n" +
"Rf9q2eGVmQkAIV6YCzHuIkHpha8Q8BhzNe4udLeUCmncOXU3Y4LQGLADE5AuNnfq\n" +
"bg60Z3Jk5B5icZ6s9qd2trcpImkCgYEAwuEcWc+AYIVGDmCjkaMtUC6gsnG7kkZ5\n" +
"Di9r1BLT2EZe6GRLfAoyAwNUcILP9N7WxYa/qFiUJ5A2mKJ3YZZz5rDRX2lhQrFG\n" +
"yM3UqPdvaxJhhEfsEZS4JYYIcqd0lxZX5FiUiz/ac3FBnBYRenSJJsro3skhYL/e\n" +
"rynAOpicW2kCgYEAuSM/uJXDcK1aaK8bSYatoIw00j1/QQqZM6/AZGQDwoNX+iwg\n" +
"0JVjW/23ECMZ1m3PcAN2YkKRnbQ3tmA3X2lemu3sGiRAoLJhg5shNiyRPq7DeiFZ\n" +
"Ph/oqkSzb2GgqmG3X7+yuO/uhIEDHsIjX9A5g5QWVro2DWq5z9ir3SwTZbkCgYB5\n" +
"d7ilHholj0xwT7oEX9IxpS6SqyM/9F8mAVbTc/zJVGt5rHIEWZJ8oEm0a0TVm0QB\n" +
"EJFLjBKkalYtYy7IC/An/VQzhUqTOE4ngWwo+TlgYq+XtQCmoKz67oU7ebbJKasU\n" +
"8EV+Wgl+ZTyA3px8WEDYhicKHhGI7W8OfRaNL2xd6QKBgQCx96zU4bP3nlXmq1Dc\n" +
"EJwxv2/r+ZMSENw98r1YuaBStGUuYefWtP39Dipl5G3g2RtBOB+sM808PMGn77Vx\n" +
"s8CBRmMBQxqinheULwy/HAv3dgZoFdCQYeoql7a/pKuCUvFcYhOxGHVWfarLdXFz\n" +
"gzGIV9W0OLg3OYBfsYthezd3ug==";
public static String getServerPubKey() {
return serverPubKey;
}
public static String getServerPrvKeyPkcs8() {
return serverPrvKeyPkcs8;
}
}
写一个测试类,用公钥加密。
package com.baidu.designer;
import com.baidu.designer.rsa.RsaKeys;
import com.baidu.designer.service.RsaService;
import org.junit.After;
import org.junit.Before;
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.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ZuulApplication2000.class)
public class ZuulTest {
@Autowired
private RsaService rsaService;
@Before
public void before() throws Exception{
}
@After
public void after() throws Exception {
}
@Test
public void genEncryptDataByPubKey() {
String data = "{\"name\":\"tom\"}";
try {
String encData = rsaService.RSAEncryptDataPEM(data, RsaKeys.getServerPubKey());
System.out.println("data: " + data);
System.out.println("encData: " + encData);
} catch (Exception e) {
e.printStackTrace();
}
}
}
service:
package com.baidu.designer.service;
import java.util.HashMap;
/**
*
* @ClassName: RsaService
* @Description: rsa加密解密服务接口
* @author Mr.Yang
* @date 2020年12月20日 下午6:10:15
*
*/
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();
}
ServiceImpl:
package com.baidu.designer.service;
import com.baidu.designer.rsa.Base64Utils;
import com.baidu.designer.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();
}
}
写一个过滤器,用于获取加密密文和解密,并以json的格式进行转发。
package com.baidu.designer.fileter;
import com.baidu.designer.rsa.RsaKeys;
import com.baidu.designer.service.RsaService;
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 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;
@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容器
RequestContext ctx = RequestContext.getCurrentContext();
//获取request和response
HttpServletRequest request = ctx.getRequest();
HttpServletResponse response = ctx.getResponse();
//声明存放加密后的数据的变量
String requestData = null;
//声明存放解密后的数据变量
String decryptData = null;
try {
//通过request获取inputStream
ServletInputStream inputStream = request.getInputStream();
//从inputsteam中得到加密后的数据
requestData = StreamUtils.copyToString(inputStream, Charsets.UTF_8);
System.out.println(requestData);
//对加密后的数据进行解密操作
if (!Strings.isNullOrEmpty(requestData)) {
decryptData = rsaService.RSADecryptDataPEM(requestData, RsaKeys.getServerPrvKeyPkcs8());
System.out.println(decryptData);
}
//把解密后的数据进行转发,需要放到request中
if (!Strings.isNullOrEmpty(decryptData)) {
//获取到解密后的数据的字节数组
byte[] bytes = decryptData.getBytes();
//使用RequestContext进行数据的转发
ctx.setRequest(new HttpServletRequestWrapper(request) {
@Override
public ServletInputStream getInputStream() throws IOException {
return new ServletInputStreamWrapper(bytes);
}
@Override
public int getContentLength() {
return bytes.length;
}
@Override
public long getContentLengthLong() {
return bytes.length;
}
});
}
//需要设置request请求头中的Content-Type,为json格式的数据
//如果不设置,api接口模块就需要进行url转码的操作
ctx.addZuulRequestHeader("Content-Type",
MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}