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


證書和回調(diào)報文解密

為了保證安全性,微信支付在回調(diào)通知和平臺證書下載接口中,對關(guān)鍵信息進行了AES-256-GCM加密。本章節(jié)詳細介紹了加密報文的格式,以及如何進行解密。


加密報文格式

AES-GCM是一種NIST標準的認證加密算法, 是一種能夠同時保證數(shù)據(jù)的保密性、 完整性和真實性的一種加密模式。它最廣泛的應(yīng)用是在TLS中。

證書和回調(diào)報文使用的加密密鑰為APIv3密鑰

對于加密的數(shù)據(jù),我們使用了一個獨立的JSON對象來表示。為了方便閱讀,示例做了Pretty格式化,并加入了注釋。

{
	"original_type": "transaction", // 加密前的對象類型
	"algorithm": "AEAD_AES_256_GCM", // 加密算法

	// Base64編碼后的密文
	"ciphertext": "...",
	// 加密使用的隨機串初始化向量)
	"nonce": "...",
	// 附加數(shù)據(jù)包(可能為空)
	"associated_data": ""
}
加密的隨機串,跟簽名時使用的隨機串沒有任何關(guān)系,是不一樣的。

解密

算法接口的細節(jié),可以參考RFC 5116

大部分編程語言(較新版本)都支持了AEAD_AES_256_GCM 。開發(fā)者可以參考下列的示例,了解如何使用您的編程語言實現(xiàn)解密。

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AesUtil {

	static final int KEY_LENGTH_BYTE = 32;
	static final int TAG_LENGTH_BIT = 128;
	private final byte[] aesKey;

	public AesUtil(byte[] key) {
		if (key.length != KEY_LENGTH_BYTE) {
			throw new IllegalArgumentException("無效的ApiV3Key,長度必須為32個字節(jié)");
		}
		this.aesKey = key;
	}

	public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
	throws GeneralSecurityException, IOException {
		try {
			Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

			SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
			GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);

			cipher.init(Cipher.DECRYPT_MODE, key, spec);
			cipher.updateAAD(associatedData);

			return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			throw new IllegalStateException(e);
		} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
			throw new IllegalArgumentException(e);
		}
	}
}
class AesUtil {
	/**
	 * AES key
	 *
	 * @var string
	 */
	private $aesKey;

	const KEY_LENGTH_BYTE = 32;
	const AUTH_TAG_LENGTH_BYTE = 16;

	/**
	 * Constructor
	 */
	public
	function __construct($aesKey) {
		if (strlen($aesKey) != self::KEY_LENGTH_BYTE) {
			throw new InvalidArgumentException('無效的ApiV3Key,長度應(yīng)為32個字節(jié)');
		}
		$this - > aesKey = $aesKey;
	}

	/**
	 * Decrypt AEAD_AES_256_GCM ciphertext
	 *
	 * @param string    $associatedData     AES GCM additional authentication data
	 * @param string    $nonceStr           AES GCM nonce
	 * @param string    $ciphertext         AES GCM cipher text
	 *
	 * @return string|bool      Decrypted string on success or FALSE on failure
	 */
	public
	function decryptToString($associatedData, $nonceStr, $ciphertext) {
		$ciphertext = \base64_decode($ciphertext);
		if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
			return false;
		}

		// ext-sodium (default installed on >= PHP 7.2)
		if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) {
			return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this - > aesKey);
		}

		// ext-libsodium (need install libsodium-php 1.x via pecl)
		if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') && \Sodium\crypto_aead_aes256gcm_is_available()) {
			return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this - > aesKey);
		}

		// openssl (PHP >= 7.1 support AEAD)
		if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
			$ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
			$authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);

			return \openssl_decrypt($ctext, 'aes-256-gcm', $this - > aesKey, \OPENSSL_RAW_DATA, $nonceStr,
				$authTag, $associatedData);
		}

		throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安裝libsodium-php');
	}
}
public class AesGcm
{
    private static string ALGORITHM = "AES/GCM/NoPadding";
    private static int TAG_LENGTH_BIT = 128;
    private static int NONCE_LENGTH_BYTE = 12;
    private static string AES_KEY = "yourkeyhere";

    public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext)
    {
        GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
        AeadParameters aeadParameters = new AeadParameters(
            new KeyParameter(Encoding.UTF8.GetBytes(AES_KEY)), 
            128, 
            Encoding.UTF8.GetBytes(nonce), 
            Encoding.UTF8.GetBytes(associatedData));
        gcmBlockCipher.Init(false, aeadParameters);

        byte[] data = Convert.FromBase64String(ciphertext);
        byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
        int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
        gcmBlockCipher.DoFinal(plaintext, length);
        return Encoding.UTF8.GetString(plaintext);
    }
}
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import base64

def decrypt(nonce, ciphertext, associated_data):
    key = "Your32Apiv3Key"

    key_bytes = str.encode(key)
    nonce_bytes = str.encode(nonce)
    ad_bytes = str.encode(associated_data)
    data = base64.b64decode(ciphertext)

    aesgcm = AESGCM(key_bytes)
    return aesgcm.decrypt(nonce_bytes, data, ad_bytes)


技術(shù)咨詢

文檔反饋