在Golang中,我们可以使用第三方库来进行HS、RS、ES和ED签名与验证。
- HS(HMAC-SHA)签名与验证
对于HS签名算法,我们可以使用crypto/hmac包生成签名,并使用常规的字符串比较来验证签名。下面是示例代码:
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
)
func generateHMAC(key []byte, data []byte) ([]byte, error) {
h := hmac.New(sha256.New, key)
_, err := h.Write(data)
if err != nil {
return nil, err
}
return h.Sum(nil), nil
}
func verifyHMAC(key []byte, data []byte, signature []byte) bool {
generatedSig, _ := generateHMAC(key, data)
return hmac.Equal(signature, generatedSig)
}
func main() {
key := []byte("mykey")
data := []byte("hello world")
// 签名数据
signature, err := generateHMAC(key, data)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(signature))
// 验证签名
isValid := verifyHMAC(key, data, signature)
fmt.Println(isValid)
}
在上面的代码中,我们使用了crypto/hmac包生成了一个sha256哈希值的HMAC-SHA签名,并将其编码为base64字符串输出。然后我们又定义了一个函数用于验证该签名是否有效。
- RS(RSA)签名与验证
对于RS签名算法,我们可以使用crypto/rsa包生成签名,并使用x509标准库验证签名。下面是示例代码:
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
)
func generateRSASignature(privateKey *rsa.PrivateKey, data []byte) ([]byte, error) {
hashed := sha256.Sum256(data)
return rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])
}
func verifyRSASignature(publicKey *rsa.PublicKey, data []byte, signature []byte) bool {
hashed := sha256.Sum256(data)
err := rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], signature)
return err == nil
}
func main() {
privatePEM := `
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvhyMBkTq8V2LgDlH0iS+F5+5IzJmWivNQ6atRyU7vgBnpLsX
f1SoC4sz7hDhZ4Pey3BQaOfevQwHcNNmFj6XpYVnU6qNTBV85Cv5GK0d0mXliYb9
dPGDEc+yTD3XC78FJ/kwcrpSKqIFrMdTsl9eKtMUkizPnzS/WuErxagZqXh7IY04
9SPNz92sfDmQDD+pqWcaAE09fRsLiZdR8WXJl+CZRXY8xTfZcCJGkhYX2tq5C3hW
4jB/75i50aeKw5L8sQa9YBbno8XnSlxjOkD0Oo1mH+PRezFyUd7v6gKFZElBWwM+
I3/xKbUVkFGRW+f2u34VqRkiNlTNUeVQTWHgqwIDAQABAoIBAQCNKsbzJwpE3kAq
90oc6nUUGAxV99t/s9AJvZJtS1rSaIme/Pp/gmdVRDWX/LArwkxBhTN28jlMrMAO
COxZLGzkaxwbeZEp+8LVWtfnbl+yr0MPkkpljmFuCKlr/+ltEKTkLu/i3M10EVbj
in/YZZe47Tk8vKddbhRL4OdQ/Cpcp4gDOhpFPhPC0nVKPLF05TVoejoTtBwSGARL
dm/mSCs4OUYayfGibVGPHh7PrvnkmMtG/GVIaet6IVSJxz98IJHVsmRIbHKAB26M
5++rHYiKr2ypndtQDMXiZ/zgr15uxPB59RgTZHjTXzlDJlvfiTmVMYi/RYlkHNig
dPFv9vjxAoGBAOwllGEld+shcvRM/qNgTjKgu6sfpoFPlwo30lnmqDpIZPW78+xP
44JPiykoyckSD+MVjia91ER43Wy14vfptzGX7qN2Qpb6dWJpKtY9h8xPZ4+siGkC
3L2Iws1wubVUvFzHb7C0yOc/aX+bBf5fRPcgTxzTQlnWgkZYu7bZjS/lAoGBAMmm
nGMqwEowDp3sVqExTYlTrSpEVTgc6e1py4zyr7RmOwhL+oGtSENNrnWclxzO8A5i
+p88XZZNzrONaPfi/Vrs50jQmM3vxdZVmTug0Xn/38rlMX06hIH/RBHx/g/HzYPA
JU71H45VtFDIqMZQ57GRJbQLToNgY2xsaBe6mbqxAoGBAKO5DBA9geUMpwzvMsf/
XL1cqENwYLmSPrcWyIaRXe/NhuHPMAvpukNBFTT5dqfJDAmpPPVOlKcVOfckqcTm
yEwmavLc+QUhLPAn2NnPbyto+hNTKYy5J4CmaGJ9ijrTIrFZDGPTOsDdvl41ZeR6
V37vHlmOk8Saq67/nVBfNoXJAoGBAJKhMH8xbtzIfFnWzsRwFJS65YehysUNmjyx
dddl5n3NXB0T5ixfgz1TDg/D3CUfhcxCRFL10iBvm9gFCYjhCWhAXpLsnELFeRL0
KkJ3twz1b0GKyCpKqP9cT4dHsUy2sXN9z7Phk9+OJ/PoVzz8vQrF5EKZl0kLmteS
a26u6MjBAoGBAJTKR/7wUvNAGlzSPxIyZXrrS4ixRsP1tQfYKK3SueipRLURDnMF
a8FZphmnoWLDhHNK4htWJaqUTA90itEiRXMMduVgvywqpB5cshwjQMye+Tt+2gNr
IXYxzyFLvWhBaGT/+RRNM8OcgzOEEhiL/UtsKzjCMFdCXjwM/xscFDNG
-----END RSA PRIVATE KEY-----
`
publicPEM := `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhyMBkTq8V2LgDlH0iS+
F5+5IzJmWivNQ6atRyU7vgBnpLsXf1SoC4sz7hDhZ4Pey3BQaOfevQwHcNNmFj6X
pYVnU6qNTBV85Cv5GK0d0mXliYb9dPGDEc+yTD3XC78FJ/kwcrpSKqIFrMdTsl9e
KtMUkizPnzS/WuErxagZqXh7IY049SPNz92sfDmQDD+pqWcaAE09fRsLiZdR8WXJ
l+CZRXY8xTfZcCJGkhYX2tq5C3hW4jB/75i50aeKw5L8sQa9YBbno8XnSlxjOkD0
Oo1mH+PRezFyUd7v6gKFZElBWwM+I3/xKbUVkFGRW+f2u34VqRkiNlTNUeVQTWHg
qwIDAQAB
-----END PUBLIC KEY-----
`
privateBlock, _ := pem.Decode([]byte(privatePEM))
if privateBlock == nil {
panic("failed to decode private key")
}
privateKey, err := x509.ParsePKCS1PrivateKey(privateBlock.Bytes)
if err != nil {
panic(err)
}
publicBlock, _ := pem.Decode([]byte(publicPEM))
if publicBlock == nil {
panic("failed to decode public key")
}
publicKeyInterface, err := x509.ParsePKIXPublicKey(publicBlock.Bytes)
if err != nil {
panic(err)
}
publicKey, ok := publicKeyInterface.(*rsa.PublicKey)
if !ok {
panic("public key is not of type *rsa.PublicKey")
}
data := []byte("hello world")
// 签名数据
signature, err := generateRSASignature(privateKey, data)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(signature))
// 验证签名
isValid := verifyRSASignature(publicKey, data, signature)
fmt.Println(isValid)
在上面的代码中,我们使用了crypto/rsa包生成了一个SHA256哈希值的RSA签名,并将其编码为base64字符串输出。然后我们又定义了一个函数用于验证该签名是否有效。
- ES(ECDSA)签名与验证
对于ES签名算法,我们可以使用crypto/ecdsa包生成签名,并使用x509标准库验证签名。下面是示例代码:
”` package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/pem"
"fmt"
)
func generateECDSASignature(privateKey *ecdsa.PrivateKey, data []byte) ([]byte, error) {
hashed := sha256.Sum256(data)
return ecdsa.SignASN1(rand.Reader, privateKey, hashed[:])
}
func verifyECDSASignature(publicKey *ecdsa.PublicKey, data []byte, signature []byte) bool {
hashed := sha256.Sum256(data)
return ecdsa.VerifyASN1(publicKey, hashed[:], signature)
}
func main() {
privatePEM := `
—–BEGIN EC PRIVATE KEY—– MHcCAQEEIPKQEZgH4u/rT6lQy7VxxTm2UyA+9Zwmp3M+bIq0V8BSoAoGCCqGSM49 AwEHoUQDQgAE5XbNzP5Otnp4oPGt/lJwCvLjpsnWd9FgrqiLkex7aRaeizHHT+9W EBmt4fOPZiAtzS6nI4eFYNOlgoYkkUG/hw== —–END EC PRIVATE KEY—– `
publicPEM := `
—–BEGIN PUBLIC KEY—– MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5XbNzP5Otnp4oPGt/lJwCvLjpsnW d9FgrqiLkex7aRaeizHHT+9WEBmt4fOPZiAtzS6nI4eFYNOlgoYkkUG/hw== —–END PUBLIC KEY—– `
privateBlock, _ := pem.Decode([]byte(privatePEM))
if privateBlock == nil {
panic("failed to decode private key")
}
privateKey, err := x509.ParseECPrivateKey(privateBlock.Bytes)
if err != nil {
panic(err)
}
publicBlock, _ := pem.Decode([]byte(publicPEM))
if publicBlock == nil {
panic("failed to decode public key")
}
publicKeyInterface, err := x509.ParsePKIXPublicKey(publicBlock.Bytes)
if err != nil {
panic(err)
}
publicKey, ok