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

Login expired. Please log in again.

Feedback

0/300

Feedback

Submitted successfully

ok

Feedback

Network exception, please try again later

ok

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

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

1. 加密報(bào)文格式

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

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

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

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

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

2. 解密

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

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

package com.wechat.v3;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.wechat.pay.contrib.apache.httpclient.exception.ParseException;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;

import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;


class DecodeCipher {

    private static final String apiV3Key = "";

    private void setDecryptData(Notification notification) throws ParseException {

        Notification.Resource resource = notification.getResource();
        String getAssociateddData = "";
        if (resource.getAssociatedData() != null) {
            getAssociateddData = resource.getAssociatedData();
        }
        byte[] associatedData = getAssociateddData.getBytes(StandardCharsets.UTF_8);
        byte[] nonce = resource.getNonce().getBytes(StandardCharsets.UTF_8);
        String ciphertext = resource.getCiphertext();
        AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
        String decryptData;
        try {
            decryptData = aesUtil.decryptToString(associatedData, nonce, ciphertext);
        } catch (GeneralSecurityException e) {
            throw new ParseException("AES解密失敗,resource:" + resource.toString(), e);
        }
        notification.setDecryptData(decryptData);
    }


    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Notification {

        @JsonProperty("id")
        private String id;
        @JsonProperty("create_time")
        private String createTime;
        @JsonProperty("event_type")
        private String eventType;
        @JsonProperty("resource_type")
        private String resourceType;
        @JsonProperty("summary")
        private String summary;
        @JsonProperty("resource")
        private Resource resource;
        private String decryptData;

        @Override
        public String toString() {
            return "Notification{" +
                    "id='" + id + '\'' +
                    ", createTime='" + createTime + '\'' +
                    ", eventType='" + eventType + '\'' +
                    ", resourceType='" + resourceType + '\'' +
                    ", decryptData='" + decryptData + '\'' +
                    ", summary='" + summary + '\'' +
                    ", resource=" + resource +
                    '}';
        }

        public String getId() {
            return id;
        }

        public String getCreateTime() {
            return createTime;
        }

        public String getEventType() {
            return eventType;
        }

        public String getDecryptData() {
            return decryptData;
        }

        public String getSummary() {
            return summary;
        }

        public String getResourceType() {
            return resourceType;
        }

        public Resource getResource() {
            return resource;
        }

        public void setDecryptData(String decryptData) {
            this.decryptData = decryptData;
        }

        @JsonIgnoreProperties(ignoreUnknown = true)
        public class Resource {

            @JsonProperty("algorithm")
            private String algorithm;
            @JsonProperty("ciphertext")
            private String ciphertext;
            @JsonProperty("associated_data")
            private String associatedData;
            @JsonProperty("nonce")
            private String nonce;
            @JsonProperty("original_type")
            private String originalType;

            public String getAlgorithm() {
                return algorithm;
            }

            public String getCiphertext() {
                return ciphertext;
            }

            public String getAssociatedData() {
                return associatedData;
            }

            public String getNonce() {
                return nonce;
            }

            public String getOriginalType() {
                return originalType;
            }

            @Override
            public String toString() {
                return "Resource{" +
                        "algorithm='" + algorithm + '\'' +
                        ", ciphertext='" + ciphertext + '\'' +
                        ", associatedData='" + associatedData + '\'' +
                        ", nonce='" + nonce + '\'' +
                        ", originalType='" + originalType + '\'' +
                        '}';
            }
        }

    }
}
<?php
require_once('vendor/autoload.php');

use WeChatPay\Crypto\Rsa;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Formatter;

$inWechatpaySignature = '';// Get this value from the header in response
$inWechatpayTimestamp = '';// Get this value from the header in response
$inWechatpaySerial = '';// Get this value from the header in response
$inWechatpayNonce = '';// Get this value from the header in response
$inBody = '';// Get this value from the body in response
$apiv3Key = '';
$platformPublicKeyInstance = Rsa::from('file:///path/to/wechatpay/inWechatpaySerial.pem', Rsa::KEY_TYPE_PUBLIC);

$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
    Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
    $inWechatpaySignature,
    $platformPublicKeyInstance
);
if ($timeOffsetStatus && $verifiedStatus) {
    $inBodyArray = (array)json_decode($inBody, true);
    ['resource' => [
        'ciphertext'      => $ciphertext,
        'nonce'           => $nonce,
        'associated_data' => $aad
    ]] = $inBodyArray;
    $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
    $inBodyResourceArray = (array)json_decode($inBodyResource, true);
}
package wechatpay

import (
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
)

// DecryptAES256GCM 使用 AEAD_AES_256_GCM 算法進(jìn)行解密
//
// 你可以使用此算法完成微信支付平臺證書和回調(diào)報(bào)文解密,詳見:
// https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi
func DecryptAES256GCM(aesKey, associatedData, nonce, ciphertext string) (plaintext string, err error) {
	decodedCiphertext, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		return "", err
	}
	c, err := aes.NewCipher([]byte(aesKey))
	if err != nil {
		return "", err
	}
	gcm, err := cipher.NewGCM(c)
	if err != nil {
		return "", err
	}
	dataBytes, err := gcm.Open(nil, []byte(nonce), decodedCiphertext, []byte(associatedData))
	if err != nil {
		return "", err
	}
	return string(dataBytes), nil
}
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)
    頁面導(dǎo)航

About  WeChat  Pay

Powered By Tencent & Tenpay Copyright©

2005-2024 Tenpay All Rights Reserved.

Contact Us
Wechat Pay Global

WeChat Pay Global

置頂