github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/crypto/secp256k1/secp256k1_nocgo.go (about) 1 //go:build !libsecp256k1 2 3 package secp256k1 4 5 import ( 6 "github.com/btcsuite/btcd/btcec/v2" 7 "github.com/btcsuite/btcd/btcec/v2/ecdsa" 8 "github.com/decred/dcrd/dcrec/secp256k1/v4" 9 10 "github.com/gnolang/gno/tm2/pkg/crypto" 11 ) 12 13 // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg. 14 // The returned signature will be of the form R || S (in lower-S form). 15 func (privKey PrivKeySecp256k1) Sign(msg []byte) ([]byte, error) { 16 priv, _ := btcec.PrivKeyFromBytes(privKey[:]) 17 18 sig, err := ecdsa.SignCompact(priv, crypto.Sha256(msg), false) // ref uncompressed pubkey 19 if err != nil { 20 return nil, err 21 } 22 23 // remove compact sig recovery code byte at the beginning 24 return sig[1:], nil 25 } 26 27 // VerifyBytes verifies a signature of the form R || S. 28 // It rejects signatures which are not in lower-S form. 29 func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sigStr []byte) bool { 30 if len(sigStr) != 64 { 31 return false 32 } 33 34 pub, err := secp256k1.ParsePubKey(pubKey[:]) 35 if err != nil { 36 return false 37 } 38 39 psig, ok := signatureFromBytes(sigStr) 40 if !ok { 41 return false 42 } 43 44 return psig.Verify(crypto.Sha256(msg), pub) 45 } 46 47 // Read Signature struct from R || S. Caller needs to ensure 48 // that len(sigStr) == 64. 49 func signatureFromBytes(sigStr []byte) (*ecdsa.Signature, bool) { 50 // parse the signature: 51 var r, s secp256k1.ModNScalar 52 if r.SetByteSlice(sigStr[:32]) { 53 return nil, false // overflow 54 } 55 if s.SetByteSlice(sigStr[32:]) { 56 return nil, false 57 } 58 59 // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. 60 if s.IsOverHalfOrder() { 61 return nil, false 62 } 63 64 return ecdsa.NewSignature(&r, &s), true 65 }