Skip to content

RSA

RSA 数字签名是一种基于非对称加密的数字签名算法,使用私钥进行签名,公钥进行验证。dongle 支持标准 RSA 数字签名,提供多种密钥格式、哈希算法和输出格式。

支持以下密钥格式:

  • PKCS1:PKCS#1 格式,使用 PKCS1v15 填充模式,无需指定哈希算法
  • PKCS8:PKCS#8 格式,使用 PSS 填充模式,必须指定哈希算法,提供更好的安全性

支持以下哈希算法:

  • MD4:MD4 哈希算法(不推荐用于生产环境)
  • MD5:MD5 哈希算法(不推荐用于生产环境)
  • SHA1:SHA-1 哈希算法(不推荐用于生产环境)
  • SHA224:SHA-224 哈希算法
  • SHA256:SHA-256 哈希算法(推荐)
  • SHA384:SHA-384 哈希算法
  • SHA512:SHA-512 哈希算法
  • MD5SHA1:MD5-SHA1 哈希算法
  • RIPEMD160:RIPEMD160 哈希算法
  • SHA3_224:SHA3_224 哈希算法
  • SHA3_256:SHA3_256 哈希算法
  • SHA3_384:SHA3_384 哈希算法
  • SHA3_512:SHA3_512 哈希算法
  • SHA512_224:SHA512_224 哈希算法
  • SHA512_256:SHA512_256 哈希算法
  • BLAKE2s_256:BLAKE2s_256 哈希算法
  • BLAKE2b_256:BLAKE2b_256 哈希算法
  • BLAKE2b_384:BLAKE2b_384 哈希算法
  • BLAKE2b_512:BLAKE2b_512 哈希算法

注意事项:

  • 密钥长度:推荐使用 2048 位或更长的密钥长度以确保安全性
  • 密钥格式:推荐使用 PKCS8 格式,它使用更安全的 PSS 填充模式
  • 哈希算法:推荐使用 SHA256 或更强的哈希算法,避免使用 MD5SHA1
  • 私钥安全:私钥必须妥善保管,不能泄露,只有私钥持有者才能生成有效签名
  • 签名验证:任何人都可以使用公钥验证签名的有效性

创建密钥对

go
import (
	"crypto"
	"github.com/dromara/dongle/crypto/keypair"
)

kp := keypair.NewRsaKeyPair()
// 设置密钥格式(可选,默认为 PKCS8)
kp.SetFormat(keypair.PKCS8)
// 设置哈希算法(可选,默认为 SHA256)
kp.SetHash(crypto.SHA256)

生成密钥对

go
// 生成 2048 位密钥对
kp.GenKeyPair(2048)

// 获取 PEM 格式公钥
publicKey := kp.PublicKey  
// 获取 PEM 格式私钥
privateKey := kp.PrivateKey

从已有 PEM 密钥设置密钥对

go
// 设置 PEM 格式公钥
kp.PublicKey = []byte(`-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqzZNa9VrcewyU6wDoV7Y9kAHq
X1VK0B3Rb6GNmQe4zLEfce7cVTaLrc4VGTKl35tADG1cRHqtaG4S/WttpiGZBhxJ
y4MpOXb6eIPiVLsn2lL+rJo5XdbSr3gyjxEOQQ97ihtw4lDd5wMo4bIOuw1LtMez
HC1outlM6x+/BB0BSQIDAQAB
-----END PUBLIC KEY-----`)

// 设置 PEM 格式私钥
kp.PrivateKey = []byte(`-----BEGIN PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKrNk1r1Wtx7DJTr
AOhXtj2QAepfVUrQHdFvoY2ZB7jMsR9x7txVNoutzhUZMqXfm0AMbVxEeq1obhL9
a22mIZkGHEnLgyk5dvp4g+JUuyfaUv6smjld1tKveDKPEQ5BD3uKG3DiUN3nAyjh
sg67DUu0x7McLWi62UzrH78EHQFJAgMBAAECgYAeo3nHWzPNURVUsUMcan96U5bE
YA2AugxfQVMNf2HvOGidZ2adh3udWrQY/MglERNcTd5gKriG2rDEH0liBecIrNKs
BL4lV+qHEGRUcnDDdtUBdGInEU8lve5keDgmX+/huXSRJ+3tYA5u9j+32RquVczv
Idtb5XnBLUl61k0osQJBAON5+eJjtw6xpn+pveU92BSHvaJYVyrLHwUjR07aNKb7
GlGVM3MGf1FCa8WQUo9uUzYxGLtg5Qf3sqwOrwPd5UsCQQDAOF/zWqGuY3HfV/1w
giXiWp8rc+S8tanMj5M37QQbYW5YLjUmJImoklVahv3qlgLZdEN5ZSueM5jfoSFt
Nts7AkBKoRDvSiGbi4MBbTHkzLZgfewkH/FxE7S4nctePk553fXTgCyh9ya8BRuQ
dHnxnpNkOxVPHEnnpEcVFbgrf5gjAkB7KmRI4VTiEfRgINhTJAG0VU7SH/N7+4cuf
PzfA+7ywG5c8Fa79wOB0SoB1KeUjcSLo5Ssj2fwea1F9dAeU90LAkBJQFofveaD
a3YlN4EQZOcCvJKmg7xwWuGxFVTZDVVEws7UCQbEOEEXZrNd9x0IF5kpPLR+rxua
RPgUNaDGIh5o
-----END PRIVATE KEY-----`)

从已有 PEM 密钥文件加载密钥对

go
// 从 PEM 文件加载公钥
publicKeyFile, _ := os.Open("public_key.pem")
kp.LoadPublicKey(publicKeyFile)

// 从 PEM 文件加载私钥
privateKeyFile, _ := os.Open("private_key.pem")
kp.LoadPrivateKey(privateKeyFile)

从已有字符串密钥设置密钥对

go
// 设置字符串格式公钥,会自动转换成对应的 PEM 格式公钥
kp.SetPublicKey([]byte("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqzZNa9VrcewyU6wDoV7Y9kAHqX1VK0B3Rb6GNmQe4zLEfce7cVTaLrc4VGTKl35tADG1cRHqtaG4S/WttpiGZBhxJy4MpOXb6eIPiVLsn2lL+rJo5XdbSr3gyjxEOQQ97ihtw4lDd5wMo4bIOuw1LtMezHC1outlM6x+/BB0BSQIDAQAB"))
// 设置字符串格式私钥,会自动转换成对应的 PEM 格式私钥
kp.SetPrivateKey([]byte("MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKrNk1r1Wtx7DJTrAOhXtj2QAepfVUrQHdFvoY2ZB7jMsR9x7txVNoutzhUZMqXfm0AMbVxEeq1obhL9a22mIZkGHEnLgyk5dvp4g+JUuyfaUv6smjld1tKveDKPEQ5BD3uKG3DiUN3nAyjhsg67DUu0x7McLWi62UzrH78EHQFJAgMBAAECgYAeo3nHWzPNURVUsUMcan96U5bEYA2AugxfQVMNf2HvOGidZ2adh3udWrQY/MglERNcTd5gKriG2rDEH0liBecIrNKsBL4lV+qHEGRUcnDDdtUBdGInEU8lve5keDgmX+/huXSRJ+3tYA5u9j+32RquVczvIdtb5XnBLUl61k0osQJBAON5+eJjtw6xpn+pveU92BSHvaJYVyrLHwUjR07aNKb7GlGVM3MGf1FCa8WQUo9uUzYxGLtg5Qf3sqwOrwPd5UsCQQDAOF/zWqGuY3HfV/1wgiXiWp8rc+S8tanMj5M37QQbYW5YLjUmJImoklVahv3qlgLZdEN5ZSueM5jfoSFtNts7AkBKoRDvSiGbi4MBbTHkzLZgfewkH/FxE7S4nctePk553fXTgCyh9ya8BRuQdHnxnpNkOxVPHEnnpEcVFbgrf5gjAkB7KmRI4VTiEfRgINhTJAG0VU7SH/N7+4cufPzfA+7ywG5c8Fa79wOB0SoB1KeUjcSLo5Ssj2fwea1F9dAeU90LAkBJQFofveaDa3YlN4EQZOcCvJKmg7xwWuGxFVTZDVVEws7UCQbEOEEXZrNd9x0IF5kpPLR+rxuaRPgUNaDGIh5o"))

生成签名

输入数据

go
// 输入字符串
signer := dongle.Sign.FromString("hello world").ByRsa(kp)
// 输入字节切片
signer := dongle.Sign.FromBytes([]byte("hello world")).ByRsa(kp)
// 输入文件流
file, _ := os.Open("test.txt")
signer := dongle.Sign.FromFile(file).ByRsa(kp)

// 检查签名错误
if signer.Error != nil {
	fmt.Printf("签名错误: %v\n", signer.Error)
	return
}

输出数据

go
// 输出 Hex 编码签名字符串
hexString := signer.ToHexString() // 7fae94fd1a8b880d8d5454dd8df30c40...
// 输出 Hex 编码签名字节切片
hexBytes := signer.ToHexBytes()  // []byte("7fae94fd1a8b880d8d5454dd8df30c40...")

// 输出 Base64 编码签名字符串
base64String := signer.ToBase64String() // f66U/RqLiA2NVFTdjfMMQA==...
// 输出 Base64 编码签名字节切片
base64Bytes := signer.ToBase64Bytes()  // []byte("f66U/RqLiA2NVFTdjfMMQA==...")

// 输出 原始 签名字符串
rawString := signer.ToRawString()
// 输出 原始 签名字节切片
rawBytes := signer.ToRawBytes()

验证签名

输入数据

go
// 设置 Hex 编码签名
kp.SetHexSign(hexBytes)
// 设置 Base64 编码签名
kp.SetBase64Sign(base64Bytes)
// 设置 原始 签名
kp.SetRawSign(rawBytes)

// 输入字符串
verifier := dongle.Verify.FromString("hello world").ByRsa(kp)
// 输入字节切片
verifier := dongle.Verify.FromBytes([]byte("hello world")).ByRsa(kp)
// 输入文件流
file, _ := os.Open("test.txt")
verifier := dongle.Verify.FromFile(file).ByRsa(kp)

// 检查验证错误
if verifier.Error != nil {
	fmt.Printf("验证错误: %v\n", verifier.Error)
	return
}

输出数据

go
// 输出验证结果
verifier.ToBool() // true 或 false

基于 MIT 许可发布,未经许可禁止任何形式的转载