package signature
import (
"crypto"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
)
func VerifySHA256RSA(body []byte, signatureBase64 string, publicKeyPEM []byte) error {
block, _ := pem.Decode(publicKeyPEM)
if block == nil {
return fmt.Errorf("decode public key PEM")
}
publicKey, err := parseRSAPublicKey(block.Bytes)
if err != nil {
return err
}
signature, err := base64.StdEncoding.DecodeString(signatureBase64)
if err != nil {
return fmt.Errorf("decode Base64 signature: %w", err)
}
digest := sha256.Sum256(body)
if err := rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, digest[:], signature); err != nil {
return fmt.Errorf("verify signature: %w", err)
}
return nil
}
func parseRSAPublicKey(der []byte) (*rsa.PublicKey, error) {
parsedKey, err := x509.ParsePKIXPublicKey(der)
if err == nil {
publicKey, ok := parsedKey.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("public key is not RSA")
}
return publicKey, nil
}
publicKey, pkcs1Err := x509.ParsePKCS1PublicKey(der)
if pkcs1Err != nil {
return nil, fmt.Errorf("parse RSA public key: PKIX: %v; PKCS#1: %w", err, pkcs1Err)
}
return publicKey, nil
}