github.com/cosmos/cosmos-sdk@v0.50.1/crypto/keys/secp256k1/secp256k1_nocgo.go (about) 1 //go:build !libsecp256k1_sdk 2 // +build !libsecp256k1_sdk 3 4 package secp256k1 5 6 import ( 7 "errors" 8 9 "github.com/cometbft/cometbft/crypto" 10 secp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4" 11 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 12 ) 13 14 // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg. 15 // The returned signature will be of the form R || S (in lower-S form). 16 func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) { 17 priv := secp256k1.PrivKeyFromBytes(privKey.Key) 18 sig := ecdsa.SignCompact(priv, crypto.Sha256(msg), false) 19 20 // remove the first byte which is compactSigRecoveryCode 21 return sig[1:], nil 22 } 23 24 // VerifyBytes verifies a signature of the form R || S. 25 // It rejects signatures which are not in lower-S form. 26 func (pubKey *PubKey) VerifySignature(msg, sigStr []byte) bool { 27 if len(sigStr) != 64 { 28 return false 29 } 30 pub, err := secp256k1.ParsePubKey(pubKey.Key) 31 if err != nil { 32 return false 33 } 34 // parse the signature, will return error if it is not in lower-S form 35 signature, err := signatureFromBytes(sigStr) 36 if err != nil { 37 return false 38 } 39 return signature.Verify(crypto.Sha256(msg), pub) 40 } 41 42 // Read Signature struct from R || S. Caller needs to ensure 43 // that len(sigStr) == 64. 44 // Rejects malleable signatures (if S value if it is over half order). 45 func signatureFromBytes(sigStr []byte) (*ecdsa.Signature, error) { 46 var r secp256k1.ModNScalar 47 r.SetByteSlice(sigStr[:32]) 48 var s secp256k1.ModNScalar 49 s.SetByteSlice(sigStr[32:64]) 50 if s.IsOverHalfOrder() { 51 return nil, errors.New("signature is not in lower-S form") 52 } 53 54 return ecdsa.NewSignature(&r, &s), nil 55 }