我从第三方收到未压缩格式的 ECDSA 公钥
我编写了一个基本解析器(没有任何检查),适用于我得到的特定密钥:
func HexToPublicKey(data []byte) *ecdsa.PublicKey {
x := new(big.Int).SetBytes(data[1:33])
y := new(big.Int).SetBytes(data[33:65])
pub := ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}
return &pub
}
谁能告诉我是否有更可靠的方法?
编辑:(删除参考并添加代码)
我收到的密钥格式如下:
privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
ep := privateKey.PublicKey
ep2, _ := ep.ECDH()
fmt.Printf("received public key %x\n", ep2.Bytes())
输出
received public key 0496cf21e333678b9c5cd0f6642e93f81e4544ef199ac0144404866309a139a421c5cf948b5ec8baefebaaf2af248835bf8b3f5c8570ff300c6f693f4015a39095
如果我现在将其分开,我会得到
start byte 04
X 96cf21e333678b9c5cd0f6642e93f81e4544ef199ac0144404866309a139a421
Y c5cf948b5ec8baefebaaf2af248835bf8b3f5c8570ff300c6f693f4015a39095
crypto/elliptic.Unmarshal
,但它已被弃用。有一个替代它的提案,但尚未被接受。在那之前,您可以根据该提案中的评论使用此功能:
package main
import (
"crypto/ecdh"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"errors"
"fmt"
"math/big"
)
// TODO: awaiting proposal acceptance: https://github.com/golang/go/issues/63963
func UnmarshalPublicKey(curve ecdh.Curve, bytes []byte) (*ecdsa.PublicKey, error) {
key, err := curve.NewPublicKey(bytes)
if err != nil {
return nil, err
}
// https://github.com/golang/go/issues/63963#issuecomment-1794706080
rawKey := key.Bytes()
switch key.Curve() {
case ecdh.P256():
return &ecdsa.PublicKey{
Curve: elliptic.P256(),
X: big.NewInt(0).SetBytes(rawKey[1:33]),
Y: big.NewInt(0).SetBytes(rawKey[33:]),
}, nil
case ecdh.P384():
return &ecdsa.PublicKey{
Curve: elliptic.P384(),
X: big.NewInt(0).SetBytes(rawKey[1:49]),
Y: big.NewInt(0).SetBytes(rawKey[49:]),
}, nil
case ecdh.P521():
return &ecdsa.PublicKey{
Curve: elliptic.P521(),
X: big.NewInt(0).SetBytes(rawKey[1:67]),
Y: big.NewInt(0).SetBytes(rawKey[67:]),
}, nil
default:
return nil, errors.New("cannot convert non-NIST *ecdh.PublicKey to *ecdsa.PublicKey")
}
}
func main() {
privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
publicKey := privateKey.PublicKey
ecdhKey, _ := publicKey.ECDH()
bytes := ecdhKey.Bytes()
unmarshaledPublicKey, err := UnmarshalPublicKey(ecdh.P256(), bytes)
if err != nil {
panic(err)
}
fmt.Printf("%t", publicKey.Equal(unmarshaledPublicKey)) // true
}