Hyperledger Fabric链码中ECDSA公钥转换与哈希一致性问题
问题解答
哈希结果不一致的原因及正确哈希内容
你直接哈希Go语言中ECDSAPublicKey结构体的字符串表示,本质是哈希了结构体的内存地址和字段的字符串化值,这和Node.js中KEYUTIL处理的公钥字节流完全不是同一个对象,所以结果必然不一致。
正确的哈希对象是ECDSA公钥的未压缩格式字节流——也就是Node.js中pubkeyHex对应的二进制数据。KEYUTIL返回的pubkeyHex是标准未压缩ECDSA公钥:前缀04 + 32字节X坐标 + 32字节Y坐标的十六进制形式,哈希这个字节流才会和Node.js端结果匹配。
在Go中生成pubkeyHex格式的公钥
利用Go标准库的crypto/ecdsa和crypto/x509包可以直接实现:
- 从X509证书中提取ECDSA公钥;
- 将公钥的X、Y坐标转为32字节大端字节流(不足32字节时左侧补0);
- 拼接前缀
0x04、X字节流、Y字节流,再转成十六进制字符串。
示例代码:
package main import ( "crypto/ecdsa" "crypto/sha256" "crypto/x509" "encoding/hex" "fmt" ) func getPubKeyHex(pub *ecdsa.PublicKey) string { // 处理X坐标,补全到32字节 xBytes := pub.X.Bytes() xPadded := make([]byte, 32) copy(xPadded[32-len(xBytes):], xBytes) // 处理Y坐标,补全到32字节 yBytes := pub.Y.Bytes() yPadded := make([]byte, 32) copy(yPadded[32-len(yBytes):], yBytes) // 拼接标准未压缩公钥字节流 pubBytes := append([]byte{0x04}, xPadded...) pubBytes = append(pubBytes, yPadded...) return hex.EncodeToString(pubBytes) } func main() { // 替换为你的证书字节数据 yourCertBytes := []byte("your-x509-cert-data") cert, err := x509.ParseCertificate(yourCertBytes) if err != nil { panic(err) } // 断言公钥为ECDSA类型 pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey) if !ok { panic("证书中公钥不是ECDSA类型") } // 生成pubkeyHex格式字符串 pubkeyHex := getPubKeyHex(pubKey) fmt.Println(pubkeyHex) // 以SHA256为例哈希公钥字节流 hash := sha256.Sum256(append([]byte{0x04}, append(xPadded, yPadded)...)) fmt.Println(hex.EncodeToString(hash[:])) }
哈希验证注意事项
- 确保两端使用相同的哈希算法(如SHA256、SHA1),否则结果必然不一致;
- 确认Node.js端是哈希
pubkeyHex的字符串还是对应的二进制数据,Go端要保持相同的处理逻辑。
内容的提问来源于stack exchange,提问作者Rafail K.
相关产品推荐
相关产品推荐

