微信支付分返回加密数据的解密算法实现

微信支付分回调接口中返回的数据为AES非对称密钥加密数据,需要进行解密才可读取,官方文档中只提供了JAVA、PHP、Python、GO的参考实例,未提供NodeJS版本的示例,本文提供NodeJS版本的解密实现。

1、用商户平台上设置的APIv3密钥(微信商户平台(pay.weixin.qq.com)-账户设置-API安全-设置APIv3密钥),记为key

2、针对resource.algorithm中描述的算法(目前为AEAD_AES_256_GCM),取得对应的参数nonce和associated_data。

3、使用key、nonce和associated_data,对数据密文resource.ciphertext进行解密,得到JSON形式的资源对象

注: AEAD_AES_256_GCM算法的接口细节,请参考rfc5116。微信支付使用的密钥key长度为32个字节,随机串nonce长度12个字节,associated_data长度小于16个字节并可能为空。

 /**
   * 使用AEAD_AES_256_GCM解密数据
   * @param cipherText 密文
   * @param key API V3密钥
   * @param iv nonce字符串
   * @param add associated_data字符串
   */
  decodeByAES: (cipherText: any, key: string, iv: string, add: string) => {
    let rst = '';
    cipherText = Buffer.from(cipherText, 'base64');
    let authTag = cipherText.slice(cipherText.length - 16);
    let data = cipherText.slice(0, cipherText.length - 16);
    let decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
    decipher.setAuthTag(authTag);
    decipher.setAAD(Buffer.from(add));
    rst = decipher.update(data, 'binary', 'utf8');
    try {
      rst += decipher.final('utf-8');
    } catch (e) {
      think.logger.error(e.toString());
    }
    return rst;
  },

在最终final时,会报错,抛出异常Error: Unsupported state or unable to authenticate data,我的方法是丢弃掉,因为密文可以被正常解密,这个异常参考文档 Crypter | Apps | Electron

读者如果有更合理的方法请告诉博主。

猜你喜欢

转载自blog.csdn.net/blackhost/article/details/100703911