Go语言中Brainpool曲线ECDH实现:elliptic.Unmarshal反序列化失败
解决Brainpool P512r1公钥Unmarshal失败的问题
我帮你排查了下代码,问题出在公钥的解析步骤上——你直接用elliptic.Unmarshal处理PEM解码后的字节是行不通的,原因如下:
- PEM里的
PUBLIC KEY是ASN.1 DER编码的SubjectPublicKeyInfo结构,除了椭圆曲线点(x,y),还包含算法标识、参数等元数据; elliptic.Unmarshal只接受「裸的曲线点字节」(压缩或非压缩格式),所以它无法识别带结构的公钥数据,自然返回nil。
修正后的代码
我们改用crypto/x509包的ParsePKIXPublicKey来解析完整的公钥结构,直接得到ecdsa.PublicKey对象,再进行后续的ECDH计算:
package main import ( "crypto/ecdsa" "crypto/rand" "crypto/sha256" "crypto/x509" "encoding/pem" "fmt" "io/ioutil" "log" "github.com/keybase/go-crypto/brainpool" ) func main() { fmt.Println("Hello") content, err := ioutil.ReadFile("/tmp/TEST.pem") if err != nil { log.Fatal(err) } fmt.Printf("File contents: %s", content) block, _ := pem.Decode(content) if block == nil || block.Type != "PUBLIC KEY" { log.Fatal("failed to decode PEM") } // 关键修改:用x509解析PKIX格式的公钥 pubKey, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { log.Fatalf("failed to parse public key: %v", err) } // 断言为ecdsa.PublicKey类型 pubb, ok := pubKey.(*ecdsa.PublicKey) if !ok { log.Fatal("public key is not ECDSA") } // 验证曲线是否匹配 if pubb.Curve != brainpool.P512r1() { log.Fatal("public key curve mismatch") } priva, err := ecdsa.GenerateKey(brainpool.P512r1(), rand.Reader) if err != nil { log.Fatalf("failed to generate private key: %v", err) } // ECDH计算:用私钥的D对对方公钥做ScalarMult b, _ := pubb.Curve.ScalarMult(pubb.X, pubb.Y, priva.D.Bytes()) shared1 := sha256.Sum256(b.Bytes()) fmt.Printf("\nShared key %x\n", shared1) }
额外说明
- 解析后一定要做类型断言和曲线匹配检查,避免后续出现意外错误;
- 生成私钥时别忘了处理错误(你之前忽略了err,这在生产环境中很危险);
- Keybase的go-crypto分支已经正确实现了Brainpool曲线的相关操作,只要公钥解析正确,后续的ECDH计算就能正常运行。
内容的提问来源于stack exchange,提问作者Little Code
相关产品推荐
相关产品推荐

