如何使用微信支付公钥加密敏感字段

更新时间:2024.11.20

为了保证通信过程中敏感信息字段(如用户的住址、银行卡号、手机号码等)的机密性,微信支付API v3要求商户对上送的敏感信息字段进行加密。与之相对应,微信支付会对下行的敏感信息字段进行加密,商户需解密后方能得到原文。下面详细介绍加解密的方式,以及如何进行相应的计算。

我们提供了微信支付API v3官方SDK(目前包含Java PHP Go 三种语言版本),使用官方 SDK 调用微信支付接口,无需关心签名生成和验证,接入更方便。

1. 加密算法

敏感信息加密使用的RSA公钥加密算法。加密算法使用的填充方案,我们使用了相对更安全的RSAES-OAEP(Optimal Asymmetric Encryption Padding)。

RSAES-OAEP在各个编程语言中的模式值为:

  • OpenSSL ,padding设置为RSA_PKCS1_OAEP_PADDING

  • Java,使用Cipher.getinstance(RSA/ECB/OAEPWithSHA-1AndMGF1Padding)

  • PHP,padding设置为OPENSSL_PKCS1_OAEP_PADDING

  • .NET,fOAEP设置为true

  • Node.js,padding设置为crypto.constants.RSA_PKCS1_OAEP_PADDING

  • GO,使用EncryptOAEP

开发者应当使用微信支付公钥,对上送的敏感信息进行加密。这样只有拥有私钥的微信支付才能对密文进行解密,从而保证了信息的机密性。

另一方面,微信支付使用 商户证书中的公钥对下行的敏感信息进行加密。开发者应使用商户私钥对下行的敏感信息的密文进行解密。

2. 加密示例

开发者应当使用微信支付公钥,对上送的敏感信息进行加密。

大部分编程语言支持RSA公钥加密。你可以参考示例,了解如何使用您的编程语言实现敏感信息加密。

示例代码

JAVA

1public static String rsaEncryptOAEP(String message, String publicKey)
2throws IllegalBlockSizeException, IOException {
3  try {
4    Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
5    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
6    byte[] data = message.getBytes("utf-8");
7    byte[] cipherdata = cipher.doFinal(data);
8    return Base64.getEncoder().encodeToString(cipherdata);
9  } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
10    throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
11  } catch (InvalidKeyException e) {
12    throw new IllegalArgumentException("无效的公钥", e);
13  } catch (IllegalBlockSizeException | BadPaddingException e) {
14    throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
15  }
16}

GO

1secretMessage := []byte("send reinforcements, we're going to advance")
2rng := rand.Reader
3cipherdata, err := EncryptOAEP(sha1.New(), rng, rsaPublicKey, secretMessage, nil)
4if err != nil {
5        fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
6        return
7}
8ciphertext := base64.StdEncoding.EncodeToString(cipherdata)
9fmt.Printf("Ciphertext: %s\n", ciphertext)

PHP

1private
2function getEncrypt($str) {
3  //$str是待加密字符串 
4  $public_key_path = '微信支付公钥路径';
5  $public_key = file_get_contents($public_key_path);
6  $encrypted = '';
7  if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
8    //base64编码 
9    $sign = base64_encode($encrypted);
10  } else {
11    throw new Exception('encrypt failed');
12  }
13  return $sign;
14}

CSharp

1/// 要加密的明文
2///  -----BEGIN CERTIFICATE----- 开头的string,转为bytes 
3/// 
4public static string RSAEncrypt(string text, byte[] publicKey)
5{
6  using (var rsa = (RSACryptoServiceProvider)publicKey)
7  {
8      var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), true);
9      return Convert.ToBase64String(buff);
10  }
11}

 

 

更多技术问题
技术咨询
反馈
咨询
目录
置顶