Golang中ECDSA签名的实现与使用
Golang中ECDSA签名的实现与使用 如何在Go中实现这段Python代码?
from ecdsa import SigningKey
signing_key = SigningKey.from_pem(data)
signature = signing_key.sign(to_sign_as_bytes, hashfunc=sha256, sigencode=ecdsa.util.sigencode_der)
7 回复
抱歉,可能是因为链接中的文档说明它使用的是 SHA-512,而你的代码列出的是 SHA-256。
在 crypto/ecdsa 包中有一个示例。
是的,我使用了相关的包。但我得到了一个不同的签名。我使用了Go的ecdsa.Sign()。
func main() {
fmt.Println("hello world")
}
好的,我可以尝试一下。感谢您指出这一点。
我看到了 ecdsa.go 文件的第 215 行
md := sha512.New()
ECDSA 代码是可用的。维基百科上列出的算法仅在第一步中提到了哈希函数。修改代码以使用 SHA256 可能足够简单。
// 代码示例
func main() {
fmt.Println("hello world")
}
在Go中实现ECDSA签名可以使用crypto/ecdsa和crypto/x509包。以下是等效的Go代码实现:
package main
import (
"crypto/ecdsa"
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"errors"
"math/big"
)
// 定义ASN.1结构体用于DER编码
type ecdsaSignature struct {
R, S *big.Int
}
func signWithECDSA(pemData []byte, message []byte) ([]byte, error) {
// 解析PEM格式的私钥
block, _ := pem.Decode(pemData)
if block == nil {
return nil, errors.New("failed to parse PEM block")
}
// 解析私钥
privKey, err := x509.ParseECPrivateKey(block.Bytes)
if err != nil {
return nil, err
}
// 计算消息的哈希
hash := sha256.Sum256(message)
// 使用私钥签名
r, s, err := ecdsa.Sign(nil, privKey, hash[:])
if err != nil {
return nil, err
}
// 将签名编码为DER格式
signature := ecdsaSignature{R: r, S: s}
derSignature, err := asn1.Marshal(signature)
if err != nil {
return nil, err
}
return derSignature, nil
}
// 使用示例
func main() {
// PEM格式的私钥(示例)
pemKey := `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIBp+QpYpXKX9rJ5ZQJmJvLkKzN6tW7b8fG3qHj4oOoAoGCCqGSM49
AwEHoUQDQgAE1LJk4pW+5WQn5J5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z
5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z
-----END EC PRIVATE KEY-----`
// 要签名的消息
message := []byte("Hello, ECDSA!")
// 执行签名
signature, err := signWithECDSA([]byte(pemKey), message)
if err != nil {
panic(err)
}
// 输出DER格式的签名
println("DER Signature:", signature)
}
如果需要从文件读取PEM密钥,可以这样实现:
func signFromPEMFile(filename string, message []byte) ([]byte, error) {
// 读取PEM文件
pemData, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
return signWithECDSA(pemData, message)
}
对于验证签名,可以使用以下代码:
func verifyECDSA(pemData []byte, message, signature []byte) (bool, error) {
// 解析PEM格式的公钥
block, _ := pem.Decode(pemData)
if block == nil {
return false, errors.New("failed to parse PEM block")
}
// 解析公钥
pubKey, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return false, err
}
ecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey)
if !ok {
return false, errors.New("not an ECDSA public key")
}
// 计算消息哈希
hash := sha256.Sum256(message)
// 解析DER签名
var sig ecdsaSignature
_, err = asn1.Unmarshal(signature, &sig)
if err != nil {
return false, err
}
// 验证签名
return ecdsa.Verify(ecdsaPubKey, hash[:], sig.R, sig.S), nil
}
这段Go代码实现了与Python示例相同的功能:从PEM格式的ECDSA私钥加载签名密钥,使用SHA256哈希函数对数据进行签名,并将结果编码为DER格式。

