视频一区二区三区自拍_千金肉奴隷1985未删减版在线观看_国产成人黄色视频在线播放_少女免费播放片高清在线观看_国产精品v欧美精品v


敏感信息加解密

為了保證通信過程中敏感信息字段(如用戶的住址、銀行卡號、手機號碼等)的機密性,微信支付API v3要求商戶對上送的敏感信息字段進行加密。與之相對應,微信支付會對下行的敏感信息字段進行加密,商戶需解密后方能得到原文。下面詳細介紹加解密的方式,以及如何進行相應的計算。


加密算法

敏感信息加密使用的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

開發(fā)者應當使用微信支付平臺證書中的公鑰,對上送的敏感信息進行加密。這樣只有擁有私鑰的微信支付才能對密文進行解密,從而保證了信息的機密性。

另一方面,微信支付使用 商戶證書中的公鑰對下行的敏感信息進行加密。開發(fā)者應使用商戶私鑰對下行的敏感信息的密文進行解密。

加密示例

開發(fā)者應當使用 微信支付平臺證書中的公鑰,對上送的敏感信息進行加密。

大部分編程語言支持RSA公鑰加密。你可以參考示例,了解如何使用您的編程語言實現(xiàn)敏感信息加密。

public static String rsaEncryptOAEP(String message, X509Certificate certificate)
throws IllegalBlockSizeException, IOException {
	try {
		Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
		cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());

		byte[] data = message.getBytes("utf-8");
		byte[] cipherdata = cipher.doFinal(data);
		return Base64.getEncoder().encodeToString(cipherdata);
	} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
		throw new RuntimeException("當前Java環(huán)境不支持RSA v1.5/OAEP", e);
	} catch (InvalidKeyException e) {
		throw new IllegalArgumentException("無效的證書", e);
	} catch (IllegalBlockSizeException | BadPaddingException e) {
		throw new IllegalBlockSizeException("加密原串的長度不能超過214字節(jié)");
	}
}
secretMessage := []byte("send reinforcements, we're going to advance")
rng := rand.Reader

cipherdata, err := EncryptOAEP(sha1.New(), rng, rsaPublicKey, secretMessage, nil)
if err != nil {
        fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
        return
}

ciphertext := base64.StdEncoding.EncodeToString(cipherdata)
fmt.Printf("Ciphertext: %s\n", ciphertext)
 private
function getEncrypt($str) {
	//$str是待加密字符串 
	$public_key_path = '平臺證書路徑';
	$public_key = file_get_contents($public_key_path);
	$encrypted = '';
	if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
		//base64編碼 
		$sign = base64_encode($encrypted);
	} else {
		throw new Exception('encrypt failed');
	}
	return $sign;
} 
/// 
/// 最終提交請求時,需對敏感信息加密,如身份證、銀行卡號。
/// 加密算法是RSA,使用從接口下載到的公鑰進行加密,非后臺下載到的私鑰。
/// 感謝ISV(https://github.com/ndma-isv)提供示例
/// 
/// 
/// 要加密的明文
///  -----BEGIN CERTIFICATE----- 開頭的string,轉為bytes 
/// 
public static string RSAEncrypt(string text, byte[] publicKey)
{
    using (var x509 = new X509Certificate2(publicKey))
    {
        using (var rsa = (RSACryptoServiceProvider)x509.PublicKey.Key)
        {
            var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), true);

            return Convert.ToBase64String(buff);
        }
    }
}

聲明加密使用的平臺證書

某些情況下,微信支付會更新平臺證書。這時,商戶有多個微信支付平臺證書可以用于加密。為了保證解密順利,商戶發(fā)起請求的HTTP頭部中應包括RSA公鑰加密算法,以聲明加密所用的密鑰對和證書。

  • 商戶上送敏感信息時使用微信支付平臺公鑰加密,證書序列號包含在請求HTTP頭部的Wechatpay-Serial

解密示例

微信支付使用商戶證書中的公鑰對下行的敏感信息進行加密。開發(fā)者應使用商戶私鑰對下行的敏感信息的密文進行解密。

同樣的,大部分編程語言支持RSA私鑰解密。你可以參考示例,了解如何使用您的編程語言實現(xiàn)敏感信息解密。

public static String rsaDecryptOAEP(String ciphertext, PrivateKey privateKey)
throws BadPaddingException, IOException {
	try {
		Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
		cipher.init(Cipher.DECRYPT_MODE, privateKey);

		byte[] data = Base64.getDecoder().decode(ciphertext);
		return new String(cipher.doFinal(data), "utf-8");
	} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
		throw new RuntimeException("當前Java環(huán)境不支持RSA v1.5/OAEP", e);
	} catch (InvalidKeyException e) {
		throw new IllegalArgumentException("無效的私鑰", e);
	} catch (BadPaddingException | IllegalBlockSizeException e) {
		throw new BadPaddingException("解密失敗");
	}
}
cipherdata, _ := base64.StdEncoding.DecodeString(ciphertext)
rng := rand.Reader

plaintext, err := DecryptOAEP(sha1.New(), rng, rsaPrivateKey, cipherdata, nil)
if err != nil {
  fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
  return
}

fmt.Printf("Plaintext: %s\n", string(plaintext))
 private
function getEncrypt($str) {
	//$str是待加密字符串 
	$public_key_path = '平臺證書路徑';
	$public_key = file_get_contents($public_key_path);
	$encrypted = '';
	if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
		//base64編碼 
		$sign = base64_encode($encrypted);
	} else {
		throw new Exception('encrypt failed');
	}
	return $sign;
} 
/// 
/// 最終提交請求時,需對敏感信息加密,如身份證、銀行卡號。
/// 加密算法是RSA,使用從接口下載到的公鑰進行加密,非后臺下載到的私鑰。
/// 感謝ISV(https://github.com/ndma-isv)提供示例
/// 
/// 
/// 要加密的明文
///  -----BEGIN CERTIFICATE----- 開頭的string,轉為bytes 
/// 
public static string RSAEncrypt(string text, byte[] publicKey)
{
    using (var x509 = new X509Certificate2(publicKey))
    {
        using (var rsa = (RSACryptoServiceProvider)x509.PublicKey.Key)
        {
            var buff = rsa.Encrypt(Encoding.UTF8.GetBytes(text), true);

            return Convert.ToBase64String(buff);
        }
    }
}


技術咨詢

文檔反饋