Golang RSA SHA256 签名和验签

193 阅读4分钟
package main

import (
    "crypto"
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha256"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
    "errors"
    "fmt"
    "strings"
)

const publicKeyPEM = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApphh/A/MxpxB2ZAkQy1sRiDOjPlM6EnPC7waqRcn9ydKFia879Q2xAsnxJzLdtQwOelxIHwoFY7MUoqiIPKTw7f+d1W5G1Ver/g37ZspuuUINHFCe/6bLIvEkQDBplOXrOffx72JNfZxi5jzS7Y2hwoM+/HjfxSNRKD6mIRzkRK13TmUKmfOsBrzrwGB0dP4Mf9+oEcks80xBhmNOp8aVcANVl8Ir4ijLLqRnHf1ZzpjpEw3zLggbKr68essCfHrkhkUJq28RSfSE7nGdz8lBlnQOspNU66YfIazmJ5n0HJDhr2AS4gODEqHPAnBySYJw8eF9lRr9VFixuNeaplY3QIDAQAB`

const privateKeyPEM = `MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmmGH8D8zGnEHZkCRDLWxGIM6M+UzoSc8LvBqpFyf3J0oWJrzv1DbECyfEnMt21DA56XEgfCgVjsxSiqIg8pPDt/53VbkbVV6v+Dftmym65Qg0cUJ7/pssi8SRAMGmU5es59/HvYk19nGLmPNLtjaHCgz78eN/FI1EoPqYhHORErXdOZQqZ86wGvOvAYHR0/gx/36gRySzzTEGGY06nxpVwA1WXwiviKMsupGcd/VnOmOkTDfMuCBsqvrx6ywJ8euSGRQmrbxFJ9ITucZ3PyUGWdA6yk1Trph8hrOYnmfQckOGvYBLiA4MSoc8CcHJJgnDx4X2VGv1UWLG415qmVjdAgMBAAECggEAVN1hZM8DqNUmsla8MkBsXJkPvz6sD9SxlS/AgQybvkqUcg5Pxvha4akxG/Ynq6PR4V5q03qLzNeOfCnFB3WrElOjXFUd06+8aXXPv8mAC4XqlRRxIssDb0DP5HH3M+x3YoxIMe76e7PMCanjnlj3E/lpvdpt4mmswR4kKhem62pDKHsIuWIiVJPP46IiVu3KO/upq7fOaMYI6OCFv1wmIAxUyLkB7SBR1iQYyfU3+CDdN73qUydR6Ovi7xd7BLmX5mE/1Fgu/Nlk4iZAVHduxUBijGobYjZZ4a3BpFRZSAIpP5N83rodFsZlGlNbfpHC2/wrVheSxalEAYDHPj54PQKBgQDTFqanaS85UhCsDAFkTJYAFm59upCUE8CQa0suiJ4DmdSmEk3fluXUo0BAjhyVrFEKD4Ix1z9H5xAiP1/0Lkru466EUqyw5KxLh0ErV9Rp+UqZFT7K9MIzJDzi35xtzzLgi6YsEVIKkhNQqr1VoKPtwJFYGoUeRDlSxIf71EiFxwKBgQDKClH7Y9b+WozRd7iv4Zx2S8Duj1fwfsQsfLSZqf3rDBvzlZSn8uY3q8cdAx2L50nGGIDahrGLGFftjgxPX+JdNyUv0ZyNHwJdHxOmy7aueFXNTCwBIzqr2GUG6Z+mveMy16im1ZcSAG1OEo5wTLEuQcaLVLinJW06J6n8N7lcOwKBgA3Yv4fdy348FuHiS7kTmQdacVcIBPHhtdEDaMQdrBfaYGugacFP+bWQG+fgKpna2toJGGZCk2EZFCLa+2VeIAY5ozoE3lUgOvkdXzYDpehptO4DycGweoi2SNQtDOrbG6BFKNpdLH+LA39YI+FZD0fKSP55ht/sY8I9KBpp23QDAoGASRp82Woho3zeEPixsan/c+orD+Z72j/z+WjR6/vPLVn/Tx6jYDWKSUB1VjEHYtS4I94/2VH9MagIQKMyHxJBlJrccLX2YDWFJG6XLLXvDqfp29Og5HR7ySwOOfcUVj/E0mOn2V3VQKU455PdSBLn1SXlkgqAmbH4GJ+7aNA82HsCgYEAu2Hmz2Kd7TjGTfNBFq3Qbg05soF+lh31JDpL0vj2Zf65l4m9V3MMhhWZNUwIfzbNRC64o9jMGRzCpNyzOolvXp6QRS9EXeqTILItkEivExrhP4/8VqraGx5B57wOLJLm42LXtenM/pwaipO1A2FaF7ZE/toGpU5njdvgwyGPSSo=`

func main() {
    pubKeyStr := strings.TrimSpace(publicKeyPEM)

    // Format the public key
    publicKeyStr, err := FormatRSAPublicKey(pubKeyStr)
    if err != nil {
       fmt.Printf("Error formatting public key: %v\n", err)
       return
    }

    // Print the formatted PEM encoded public key
    fmt.Println(publicKeyStr)

    // Remove any surrounding spaces or newlines
    privKeyStr := strings.TrimSpace(privateKeyPEM)

    // Format the private key
    privateKeyStr, err := FormatRSAPrivateKey(privKeyStr)
    if err != nil {
       fmt.Printf("Error formatting private key: %v\n", err)
       return
    }

    // Print the formatted PEM encoded private key
    fmt.Println(privateKeyStr)

    // 解析私钥
    privateKey, err := ParsePrivateKey(privateKeyStr)
    if err != nil {
       fmt.Println("解析私钥失败:", err)
       return
    }

    // 解析公钥
    publicKey, err := ParsePublicKey(publicKeyStr)
    if err != nil {
       fmt.Println("解析公钥失败:", err)
       return
    }

    // 原始消息
    message := []byte("2")

    //签名
    signature, err := SignMessage(privateKey, message)

    if err != nil {
       fmt.Println("Failed to sign message:", err)
       return
    }
    // 将签名结果转为 Base64 编码字符串
    signatureBase64 := base64.StdEncoding.EncodeToString(signature)
    fmt.Printf("Encrypted (signed) message: %s\n", signatureBase64)

    // 使用公钥解密(验证签名)
    err = VerifyMessage(publicKey, message, signature)
    if err != nil {
       fmt.Println("Failed to verify signature:", err)
       return
    }

    fmt.Println("Signature verified successfully, message is authentic!")
}

// RsaSign signs using private key in PEM format.
func RsaSign(pemStr string, data []byte) ([]byte, error) {
    block, _ := pem.Decode([]byte(pemStr))
    if block == nil {
       return nil, errors.New("failed to decode PEM block containing private key")
    }
    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
       return nil, err
    }

    h := sha256.Sum256(data)
    hashed := h[:]

    return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
}

// RsaVerifySign verifies signature using public key in PEM format.
// A valid signature is indicated by returning a nil error.
func RsaVerifySign(pemStr string, data, sig []byte) error {
    block, _ := pem.Decode([]byte(pemStr))
    if block == nil {
       return errors.New("decode public key error")
    }
    pub, err := x509.ParsePKIXPublicKey(block.Bytes)
    if err != nil {
       return err
    }

    h := sha256.Sum256(data)
    hashed := h[:]
    return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA256, hashed, sig)
}
```

// 解析私钥字符串
func ParsePrivateKey(pemStr string) (*rsa.PrivateKey, error) {
    // 解码 PEM 块
    block, _ := pem.Decode([]byte(pemStr))
    if block == nil || block.Type != "RSA PRIVATE KEY" {
       fmt.Println("Failed to decode PEM block containing private key")
       return nil, fmt.Errorf("Failed to decode PEM block containing private key")
    }

    // 解析 PKCS#1 格式的私钥
    privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
    if err != nil {
       return nil, fmt.Errorf("Failed to parse private key:", err)
    }
    return privateKey, nil
}

// 解析公钥字符串
func ParsePublicKey(pemStr string) (*rsa.PublicKey, error) {
    // 解码 PEM 块
    block, _ := pem.Decode([]byte(pemStr))
    if block == nil || block.Type != "RSA PUBLIC KEY" {

       return nil, fmt.Errorf("Failed to decode PEM block containing public key")
    }

    // 解析 PKCS#1 格式的公钥
    publicKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
    if err != nil {
       return nil, fmt.Errorf("Failed to parse public key:", err)
    }

    return publicKey, nil
}

// 使用私钥签名消息
func SignMessage(privateKey *rsa.PrivateKey, message []byte) ([]byte, error) {
    hashed := sha256.Sum256(message)
    return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])
}

// 使用公钥验证签名
func VerifyMessage(publicKey *rsa.PublicKey, message []byte, signature []byte) error {
    hashed := sha256.Sum256(message)
    return rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)
}

func FormatRSAPublicKey(keyStr string) (string, error) {
    // Decode the base64 encoded string
    keyBytes, err := base64.StdEncoding.DecodeString(keyStr)
    if err != nil {
       return "", fmt.Errorf("failed to decode base64 string: %v", err)
    }

    // Parse the public key
    pubKey, err := x509.ParsePKIXPublicKey(keyBytes)
    if err != nil {
       return "", fmt.Errorf("failed to parse public key: %v", err)
    }

    // Type assert to *rsa.PublicKey
    rsaPubKey, ok := pubKey.(*rsa.PublicKey)
    if !ok {
       return "", fmt.Errorf("not an RSA public key")
    }

    // Marshal the public key to PKCS#1 ASN.1 DER encoded form
    derBytes := x509.MarshalPKCS1PublicKey(rsaPubKey)

    // Create a PEM block with the DER encoded public key
    pemBlock := &pem.Block{
       Type:  "RSA PUBLIC KEY",
       Bytes: derBytes,
    }

    // Encode the PEM block to a string
    pemString := pem.EncodeToMemory(pemBlock)

    return string(pemString), nil
}

func FormatRSAPrivateKey(keyStr string) (string, error) {
    // Decode the base64 encoded string
    keyBytes, err := base64.StdEncoding.DecodeString(keyStr)
    if err != nil {
       return "", fmt.Errorf("failed to decode base64 string: %v", err)
    }

    // Parse the private key (assuming PKCS#8 format)
    privKey, err := x509.ParsePKCS8PrivateKey(keyBytes)
    if err != nil {
       return "", fmt.Errorf("failed to parse private key: %v", err)
    }

    // Type assert to *rsa.PrivateKey
    rsaPrivKey, ok := privKey.(*rsa.PrivateKey)
    if !ok {
       return "", fmt.Errorf("not an RSA private key")
    }

    // Marshal the private key to PKCS#1 ASN.1 DER encoded form
    derBytes := x509.MarshalPKCS1PrivateKey(rsaPrivKey)

    // Create a PEM block with the DER encoded private key
    pemBlock := &pem.Block{
       Type:  "RSA PRIVATE KEY",
       Bytes: derBytes,
    }

    // Encode the PEM block to a string
    pemString := pem.EncodeToMemory(pemBlock)

    return string(pemString), nil
}
```