From bbae80ae76692b34e769546346fec65a9de86fc3 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Fri, 15 Mar 2024 12:15:14 +0100 Subject: [PATCH] crypto: fix bugs on nocgo builds --- crypto/crypto.go | 9 ++++++++ crypto/signature_cgo.go | 10 --------- crypto/signature_nocgo.go | 45 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/crypto/crypto.go b/crypto/crypto.go index fd77a0d236..769793308f 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -19,6 +19,7 @@ package crypto import ( "bufio" "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" "encoding/hex" "errors" @@ -50,6 +51,14 @@ var ( var errInvalidPubkey = errors.New("invalid secp256k1 public key") +// BetterCurve is an interface that combines both a curve +// and (un)-marshalling functions to and from that curve. +type BetterCurve interface { + elliptic.Curve + Marshal(x, y *big.Int) []byte + Unmarshal(data []byte) (x, y *big.Int) +} + // KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports // Read to get a variable amount of data from the hash state. Read is faster than Sum // because it doesn't copy the internal state, but also modifies the internal state. diff --git a/crypto/signature_cgo.go b/crypto/signature_cgo.go index dd187f142d..085cbd025f 100644 --- a/crypto/signature_cgo.go +++ b/crypto/signature_cgo.go @@ -21,10 +21,8 @@ package crypto import ( "crypto/ecdsa" - "crypto/elliptic" "errors" "fmt" - "math/big" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto/secp256k1" @@ -82,14 +80,6 @@ func CompressPubkey(pubkey *ecdsa.PublicKey) []byte { return secp256k1.CompressPubkey(pubkey.X, pubkey.Y) } -// BetterCurve is an interface that combines both a curve -// and (un)-marshalling functions to and from that curve. -type BetterCurve interface { - elliptic.Curve - Marshal(x, y *big.Int) []byte - Unmarshal(data []byte) (x, y *big.Int) -} - // S256 returns an instance of the secp256k1 curve. func S256() BetterCurve { return secp256k1.S256() diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index 6d628d758d..84f31bdf56 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -21,9 +21,9 @@ package crypto import ( "crypto/ecdsa" - "crypto/elliptic" "errors" "fmt" + "math/big" "github.com/btcsuite/btcd/btcec/v2" btc_ecdsa "github.com/btcsuite/btcd/btcec/v2/ecdsa" @@ -147,6 +147,45 @@ func CompressPubkey(pubkey *ecdsa.PublicKey) []byte { } // S256 returns an instance of the secp256k1 curve. -func S256() elliptic.Curve { - return btcec.S256() +func S256() BetterCurve { + return KoblitzCurve{btcec.S256()} +} + +type KoblitzCurve struct { + *btcec.KoblitzCurve +} + +// Marshall converts a point given as (x, y) into a byte slice. +func (curve KoblitzCurve) Marshal(x, y *big.Int) []byte { + byteLen := (curve.Params().BitSize + 7) / 8 + + ret := make([]byte, 1+2*byteLen) + ret[0] = 4 // uncompressed point + + x.FillBytes(ret[1 : 1+byteLen]) + y.FillBytes(ret[1+byteLen : 1+2*byteLen]) + + return ret +} + +// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On +// error, x = nil. +func (curve KoblitzCurve) Unmarshal(data []byte) (x, y *big.Int) { + byteLen := (curve.Params().BitSize + 7) / 8 + if len(data) != 1+2*byteLen { + return nil, nil + } + if data[0] != 4 { // uncompressed form + return nil, nil + } + p := curve.Params().P + x = new(big.Int).SetBytes(data[1 : 1+byteLen]) + y = new(big.Int).SetBytes(data[1+byteLen:]) + if x.Cmp(p) >= 0 || y.Cmp(p) >= 0 { + return nil, nil + } + if !curve.IsOnCurve(x, y) { + return nil, nil + } + return }