在对接微信支付接口时,需要对微信支付返回的信息进行签名验证,防止中间人攻击,替换微信支付返回的结果
整体过程
- 微信支付生成签名:私钥 + 内容
->
signature - 调用方验证签名:公钥 + 内容
验证
signature
示例
- 生成签名
/**
* 生成签名.
*
* @param originalData 原始数据
* @param privateKey 私钥
* @return 签名串
*/
public static String sign(String originalData, PrivateKey privateKey) {
String base64Sign = "";
try {
//返回指定签名的Signature对象
Signature sign = Signature.getInstance("SHA1withRSA");
//初始化这个用于签名的对象
sign.initSign(privateKey);
byte[] bysData = originalData.getBytes(StandardCharsets.UTF_8);
//使用指定的byte数组更新要签名的数据
sign.update(bysData);
//返回所有已经更新数据的签名字节
byte[] signByte = sign.sign();
//对其进行Base64编码
BASE64Encoder encoder = new BASE64Encoder();
base64Sign = encoder.encode(signByte);
} catch (Exception e) {
throw new RuntimeException(e);
}
return base64Sign;
}
- 验证签名
/**
* 验证签名.
*
* @param signStr 签名串
* @param originalData 原始数据
* @param publicKey 公钥
* @return 是否验证通过
*/
public static boolean verify(String signStr, String originalData, PublicKey publicKey) {
System.out.println("开始进行验签,原始数据为:" + originalData);
try {
//将签名数据
BASE64Decoder decoder = new BASE64Decoder();
byte[] signed = decoder.decodeBuffer(signStr);
//通过Signature的getInstance方法,获取指定签名算法的Signature对象
Signature signature = Signature.getInstance("SHA1withRSA");
//初始化用于验证的对象
signature.initVerify(publicKey);
//使用指定的byte[]更新要验证的数据
signature.update(originalData.getBytes(StandardCharsets.UTF_8));
//验证传入的签名
return signature.verify(signed);
} catch (Exception e) {
return false;
}
}
- 测试
public static void main(String[] args) throws Exception {
String p12 = "KLFJDLJFL";
byte[] decode = Base64.getDecoder().decode(p12);
String keypasswd = "passwd";
String keyalias = "tenpay certificate";
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(new ByteArrayInputStream(decode), keypasswd.toCharArray());
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
System.out.println(aliases.nextElement());
}
PrivateKey prikey = (PrivateKey) ks.getKey(keyalias, keypasswd.toCharArray());
Certificate cert = ks.getCertificate(keyalias);
PublicKey pubkey = cert.getPublicKey();
String originData = "hello world";
String sign = sign(originData, prikey);
boolean verify = verify(sign, originData, pubkey);
System.out.println(verify);
}
疑问
使用了HTTPS,为什么微信支付还要用公私钥签名呢?
网友评论