以前公司的项目主要是一些内网用的系统,最近换了一家公司,都是面向网络用户的。有与第三方平台合作的情况,为了保证请求数据的安全,对方向我们传输数据都会对数据进行加密以及添加数字签名。我们拿到对方加密的数据后,再进行验签解密。请求对方的接口也是一样的。下面就说以一下这个过程吧
参数加密解密:
加密:我方AES密钥对data参数进行对称加密,然后在通过我方RSA私钥将data密文与其他参数拼接成字符串进行非对称加密得到sign签名。
解密:先使用对方公钥进行验签,再使用对方AES密钥进行参数解密。
下面是个参数加密解密的demo
import com.alibaba.fastjson.JSONObject;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.apache.commons.lang3.StringUtils;
import sun.misc.BASE64Decoder;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
/**
* @Description 加签、加密、验签、解密 demo
* @Date 2021/5/7
* @Version V1.0
* @Author Zhoushuang
*/
public class EncryptDemo {
private static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCE8f+k5wXFHJK7Lxeik8yVM6ky93J7QoFD9db9zLcgJhalSYgvAafqRfqPmpjnaD/1co4gmNy+oS2ZEvHIfgSuFyrmjSklQy3k+oHYVTyeQ5ypnmoMZrln70Hi4x77+zTqXRmrQBfeLpuyvl/bt98OGQaKKLiBpLl6cNUnbrSPqQIDAQAB";
private static String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAITx/6TnBcUckrsvF6KTzJUzqTL3cntCgUP11v3MtyAmFqVJiC8Bp+pF+o+amOdoP/VyjiCY3L6hLZkS8ch+BK4XKuaNKSVDLeT6gdhVPJ5DnKmeagxmuWfvQeLjHvv7NOpdGatAF94um7K+X9u33w4ZBooouIGkuXpw1SdutI+pAgMBAAECgYBi3ROfLa28x2LWkE6jOAYLbj+FBz67Ktm2EDuwwWvtHGX6xJPhYPnd3exWnkDW1U+611WaKBMAMBwYmV30GsKfGYaVhZRv1nSe+midcl7PhM+a3fItVn+mU1Idr4n7GyeYciCbiuYjRBH+GfIQmz0W1QHewE0bVUjAWX1elFBwAQJBAOqN9/4pSrLmnHz144f7PCP7VsMF/B7c77WKhs4kI9dUdrIX+fRp9qcBzSdssV/3dghMxcBGO0zu3b5MdKTE0fkCQQCRGb5AyRy7yke9NnELzeVh3KkvB+QyHAYpSH/gU+Auc8NgE0UnXPqjZG7bG/SnK75LbVnT9hRoaSy8963SQxcxAkEAw9zFR4GnlPipmFekJnsO32UUMEqhHAyWRtxkcWMQYtFvRIxs90I863y/mbpT67Uy5P9m6oY7IqUcmboydRy90QJAPDuIe5JAiD/W+deQo8rLro0P+gL3mkmB0T9UPgXzaLULZGV7bnStYog9cF0xePeyndL91/wtyo3mUWcrU74f8QJARDrh8E1on4UhWF9dC07GrbT9Ldo5NYsyXXznboUUNk5xbi4Lp0Rhp6ap2FW25oYFAe0zrcfN298gqTV+S3Uzbw==";
private static String AES_KEY = "5E769625BC89A081B0C8FFD8E5F6C0E6";
public static void main(String[] args) {
//设置基础参数
Integer pid_1 = 300055;
String channelId_1 = "BRC";
// JSONObject data_1 = JSONObject.parseObject("{\"applyId\":2100014767,\"loanAmount\":\"7000\",\"loanPeriod\":\"12\"}");
// JSONObject data_1 = JSONObject.parseObject("{\"loanId\":2100014767}");
JSONObject data_1 = JSONObject.parseObject("{\"loanId\":2100014767,\"repayType\":\"2\",\"periods\":\"1,2,3,4,5,6,7,8,9,10,11,12\"}");
Long timestamp_1 = System.currentTimeMillis();
//aes加密
String dataAES_1 = encryptAES(AES_KEY, data_1.toString());
//设置签名参数
Map<String, String> signParam_1 = new HashMap<>();
signParam_1.put("channelId", channelId_1);
signParam_1.put("data", dataAES_1);
signParam_1.put("pid", pid_1.toString());
signParam_1.put("timestamp", timestamp_1.toString());
//生成签名
String sign = Encrypt.signSHA1(signParam_1, PRIVATE_KEY);
JSONObject requestParam = new JSONObject();
requestParam.put("channelId", channelId_1);
requestParam.put("pid", pid_1);
requestParam.put("data", dataAES_1);
requestParam.put("sign", sign);
requestParam.put("timestamp", timestamp_1);
//最终的请求参数
System.out.println(requestParam.toJSONString());
//解密参数
Integer pid_2 = requestParam.getInteger("pid");
String channelId_2 = requestParam.getString("channelId");
String dataAES_2 = requestParam.getString("data");
Long timestamp_2 = requestParam.getLong("timestamp");
//检查签名
Map<String, String> signParam_2 = new HashMap<>();
signParam_2.put("pid", pid_2.toString());
signParam_2.put("channelId", channelId_2.toString());
signParam_2.put("timestamp", timestamp_2.toString());
signParam_2.put("data", dataAES_2);
boolean flag = Encrypt.checkSignSHA1(signParam_2, requestParam.getString("sign"), PUBLIC_KEY);
if (!flag) {
System.out.println("签名错误");
return;
}
System.out.println("签名正确");
//aes解密
JSONObject data_2 = JSONObject.parseObject(decryptAES(AES_KEY, dataAES_2));
System.out.println("解密后的data:" + data_2.toString());
}
/**
* ras加签、验签
*/
static class Encrypt {
/**
* 加签
*
* @param signParams
* @param privateKey
* @return
*/
public static String signSHA1(Map<String, String> signParams, String privateKey) {
return initSign("SHA1withRSA", signParams, privateKey);
}
/**
* 验签
*
* @param signParams
* @param sign
* @param publicKey
* @return
*/
public static boolean checkSignSHA1(Map<String, String> signParams, String sign, String publicKey) {
return rsa256CheckContent("SHA1withRSA", signParams, sign, publicKey);
}
private static boolean rsa256CheckContent(String signType, Map<String, String> signParams, String sign, String publicKey) {
try {
String content = getSignContent(signParams);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] encodedKey = Base64.decode(publicKey);
PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
Signature signature = Signature.getInstance(signType);
signature.initVerify(pubKey);
signature.update(content.getBytes("utf-8"));
boolean bverify = signature.verify(Base64.decode(sign));
return bverify;
} catch (Exception var10) {
var10.printStackTrace();
return false;
}
}
private static String initSign(String signType, Map<String, String> signParams, String privateKey) {
try {
String content = getSignContent(signParams);
PrivateKey priKey = getPrivateKeyFromPKCS8(privateKey);
Signature signature = Signature.getInstance(signType);
signature.initSign(priKey);
signature.update(content.getBytes("utf-8"));
byte[] signed = signature.sign();
return new String(Base64.encode(signed));
} catch (Exception var7) {
System.out.println("生成签名异常:" + var7.getMessage());
var7.printStackTrace();
return null;
}
}
public static String getSignContent(Map<String, String> sortedParams) {
StringBuffer content = new StringBuffer();
List<String> keys = new ArrayList(sortedParams.keySet());
//对key进行排序
Collections.sort(keys);
int index = 0;
for (int i = 0; i < keys.size(); ++i) {
String key = keys.get(i);
String value = sortedParams.get(key);
if (StringUtils.isNotBlank(key) && StringUtils.isNotBlank((value))) {
content.append((index == 0 ? "" : "&") + key + "=" + value);
++index;
}
}
return content.toString();
}
private static PrivateKey getPrivateKeyFromPKCS8(String priKey) {
PrivateKey privateKey = null;
if (StringUtils.isBlank(priKey)) {
return privateKey;
} else {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec((new BASE64Decoder()).decodeBuffer(priKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
privateKey = keyf.generatePrivate(priPKCS8);
} catch (Exception var4) {
System.out.println("私钥解析错误:" + var4.getMessage());
}
return privateKey;
}
}
}
/**
* aes加密
*
* @param base64Key
* @param text
* @return
*/
public static String encryptAES(String base64Key, String text) {
try {
byte[] key = parseHexStr2Byte(base64Key);
SecretKeySpec sKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(1, sKeySpec);
byte[] encryptBytes = cipher.doFinal(text.getBytes("utf-8"));
return parseByte2HexStr(encryptBytes);
} catch (Exception var6) {
System.out.println("AES加密错误:" + var6.getMessage());
return null;
}
}
/**
* aes解密
*
* @param base64Key
* @param text
* @return
*/
public static String decryptAES(String base64Key, String text) {
try {
byte[] key = parseHexStr2Byte(base64Key);
SecretKeySpec sKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(2, sKeySpec);
byte[] decryptBytes = cipher.doFinal(parseHexStr2Byte(text));
return new String(decryptBytes, "UTF-8");
} catch (Exception var6) {
System.out.println("AES解密错误:" + var6.getMessage());
return null;
}
}
private static byte[] parseHexStr2Byte(String hexStr) {
if (hexStr.length() < 1) {
return null;
} else {
byte[] result = new byte[hexStr.length() / 2];
for (int i = 0; i < hexStr.length() / 2; ++i) {
int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
result[i] = (byte) (high * 16 + low);
}
return result;
}
}
public static String parseByte2HexStr(byte[] buf) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; ++i) {
String hex = Integer.toHexString(buf[i] & 255);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
}
}