将未压缩的十六进制格式的ecdsa公钥解析为ecdsa.PublicKey

问题描述 投票:0回答:1

我从第三方收到未压缩格式的 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
go x509 elliptic-curve
1个回答
0
投票

通常您会使用

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
}
© www.soinside.com 2019 - 2024. All rights reserved.