RSA加签和验签工具类-- Golang版本实现

Golang实现RSA加签和签签工具类
package main

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

// Rsa2SignatureService 提供RSA2签名和验证功能
type Rsa2SignatureService struct{}

// Verify 验证签名是否正确
func (s *Rsa2SignatureService) Verify(content, charset, publicKey, sign string) (bool, error) {
	pubKey, err := ParsePublicKey(publicKey)
	if err != nil {
		return false, fmt.Errorf("解析公钥失败: %v", err)
	}

	contentBytes, err := getContentBytes(content, charset)
	if err != nil {
		return false, fmt.Errorf("内容编码失败: %v", err)
	}

	signBytes, err := base64.StdEncoding.DecodeString(sign)
	if err != nil {
		return false, fmt.Errorf("签名解码失败: %v", err)
	}

	hashed := sha256.Sum256(contentBytes)
	err = rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, hashed[:], signBytes)
	if err != nil {
		if errors.Is(err, rsa.ErrVerification) {
			return false, nil
		}
		return false, fmt.Errorf("验证签名时发生错误: %v", err)
	}
	return true, nil
}

// Sign 生成数字签名
func (s *Rsa2SignatureService) Sign(content, charset, privateKey string) (string, error) {
	privKey, err := ParsePrivateKey(privateKey)
	if err != nil {
		return "", fmt.Errorf("解析私钥失败: %v", err)
	}

	contentBytes, err := getContentBytes(content, charset)
	if err != nil {
		return "", fmt.Errorf("内容编码失败: %v", err)
	}

	hashed := sha256.Sum256(contentBytes)
	signature, err := rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA256, hashed[:])
	if err != nil {
		return "", fmt.Errorf("签名生成失败: %v", err)
	}
	return base64.StdEncoding.EncodeToString(signature), nil
}

// GenerateKey 生成RSA密钥对
func (s *Rsa2SignatureService) GenerateKey() (publicKey, privateKey string, err error) {
	privKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return "", "", fmt.Errorf("密钥生成失败: %v", err)
	}

	// 编码公钥
	pubKeyBytes, err := x509.MarshalPKIXPublicKey(&privKey.PublicKey)
	if err != nil {
		return "", "", fmt.Errorf("公钥编码失败: %v", err)
	}
	publicKey = base64.StdEncoding.EncodeToString(pubKeyBytes)

	// 编码私钥
	privKeyBytes, err := x509.MarshalPKCS8PrivateKey(privKey)
	if err != nil {
		return "", "", fmt.Errorf("私钥编码失败: %v", err)
	}
	privateKey = base64.StdEncoding.EncodeToString(privKeyBytes)

	return publicKey, privateKey, nil
}

func GenerateKey() (string, string, error) {
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return "", "", err
	}
	pub := &priv.PublicKey

	// 转换为 PKCS#8 私钥格式
	privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
	if err != nil {
		return "", "", err
	}

	// 转换为 X.509 公钥格式
	pubBytes, err := x509.MarshalPKIXPublicKey(pub)
	if err != nil {
		return "", "", err
	}

	privBase64 := base64.StdEncoding.EncodeToString(privBytes)
	pubBase64 := base64.StdEncoding.EncodeToString(pubBytes)

	return pubBase64, privBase64, nil
}

// ParsePublicKey 解析Base64编码的公钥
func ParsePublicKey(publicKey string) (*rsa.PublicKey, error) {
	derBytes, err := base64.StdEncoding.DecodeString(publicKey)
	if err != nil {
		return nil, err
	}

	pubKey, err := x509.ParsePKIXPublicKey(derBytes)
	if err != nil {
		return nil, err
	}

	rsaPubKey, ok := pubKey.(*rsa.PublicKey)
	if !ok {
		return nil, errors.New("非RSA公钥格式")
	}
	return rsaPubKey, nil
}

// ParsePrivateKey 解析Base64编码的私钥
func ParsePrivateKey(privateKey string) (*rsa.PrivateKey, error) {
	derBytes, err := base64.StdEncoding.DecodeString(privateKey)
	if err != nil {
		return nil, err
	}

	privKey, err := x509.ParsePKCS8PrivateKey(derBytes)
	if err != nil {
		return nil, err
	}

	rsaPrivKey, ok := privKey.(*rsa.PrivateKey)
	if !ok {
		return nil, errors.New("非RSA私钥格式")
	}
	return rsaPrivKey, nil
}

// getContentBytes 根据字符集编码内容
func getContentBytes(content, charset string) ([]byte, error) {
	if charset == "" {
		charset = "UTF-8"
	}
	switch strings.ToUpper(charset) {
	case "UTF-8":
		return []byte(content), nil
	default:
		return nil, fmt.Errorf("不支持的字符集: %s", charset)
	}
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值