// Copyright 2021 Tencent Inc. All rights reserved. // Package verifiers 微信支付 API v3 Go SDK 数字签名验证器 package verifiers import ( "context" "crypto" "crypto/rsa" "crypto/sha256" "encoding/base64" "fmt" "strings" "github.com/wechatpay-apiv3/wechatpay-go/core" ) // SHA256WithRSAVerifier SHA256WithRSA 数字签名验证器 type SHA256WithRSAVerifier struct { // Certificates 微信支付平台证书Map,key: 平台证书序列号, value: 微信支付平台证书 certGetter core.CertificateGetter } // Verify 对数字签名信息进行验证 func (verifier *SHA256WithRSAVerifier) Verify(ctx context.Context, serialNumber, message, signature string) error { err := checkParameter(ctx, serialNumber, message, signature) if err != nil { return err } if verifier.certGetter == nil { return fmt.Errorf("verifier has no validator") } sigBytes, err := base64.StdEncoding.DecodeString(signature) if err != nil { return fmt.Errorf("verify failed: signature not base64 encoded") } certificate, ok := verifier.certGetter.Get(ctx, serialNumber) if !ok { return fmt.Errorf("certificate[%s] not found in verifier", serialNumber) } hashed := sha256.Sum256([]byte(message)) err = rsa.VerifyPKCS1v15(certificate.PublicKey.(*rsa.PublicKey), crypto.SHA256, hashed[:], sigBytes) if err != nil { return fmt.Errorf("verify signature with public key err:%s", err.Error()) } return nil } // GetSerial 获取可验签的平台证书序列号 func (verifier *SHA256WithRSAVerifier) GetSerial(ctx context.Context) (string, error) { return verifier.certGetter.GetNewestSerial(ctx), nil } func checkParameter(ctx context.Context, serialNumber, message, signature string) error { if ctx == nil { return fmt.Errorf("context is nil, verifier need input context.Context") } if strings.TrimSpace(serialNumber) == "" { return fmt.Errorf("serialNumber is empty, verifier need input serialNumber") } if strings.TrimSpace(message) == "" { return fmt.Errorf("message is empty, verifier need input message") } if strings.TrimSpace(signature) == "" { return fmt.Errorf("signature is empty, verifier need input signature") } return nil } // NewSHA256WithRSAVerifier 使用 core.CertificateGetter 初始化 SHA256WithRSAVerifier func NewSHA256WithRSAVerifier(getter core.CertificateGetter) *SHA256WithRSAVerifier { return &SHA256WithRSAVerifier{certGetter: getter} }