github.com/Finschia/finschia-sdk@v0.48.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 "math/big" 8 9 secp256k1 "github.com/btcsuite/btcd/btcec" 10 11 "github.com/Finschia/ostracon/crypto" 12 ) 13 14 // used to reject malleable signatures 15 // see: 16 // - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93 17 // - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39 18 var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1) 19 20 // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg. 21 // The returned signature will be of the form R || S (in lower-S form). 22 func (privKey *PrivKey) Sign(msg []byte) ([]byte, error) { 23 priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey.Key) 24 sig, err := priv.Sign(crypto.Sha256(msg)) 25 if err != nil { 26 return nil, err 27 } 28 sigBytes := serializeSig(sig) 29 return sigBytes, nil 30 } 31 32 // VerifyBytes verifies a signature of the form R || S. 33 // It rejects signatures which are not in lower-S form. 34 func (pubKey *PubKey) VerifySignature(msg []byte, sigStr []byte) bool { 35 if len(sigStr) != 64 { 36 return false 37 } 38 pub, err := secp256k1.ParsePubKey(pubKey.Key, secp256k1.S256()) 39 if err != nil { 40 return false 41 } 42 // parse the signature: 43 signature := signatureFromBytes(sigStr) 44 // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. 45 // see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93 46 if signature.S.Cmp(secp256k1halfN) > 0 { 47 return false 48 } 49 return signature.Verify(crypto.Sha256(msg), pub) 50 } 51 52 // Read Signature struct from R || S. Caller needs to ensure 53 // that len(sigStr) == 64. 54 func signatureFromBytes(sigStr []byte) *secp256k1.Signature { 55 return &secp256k1.Signature{ 56 R: new(big.Int).SetBytes(sigStr[:32]), 57 S: new(big.Int).SetBytes(sigStr[32:64]), 58 } 59 } 60 61 // Serialize signature to R || S. 62 // R, S are padded to 32 bytes respectively. 63 func serializeSig(sig *secp256k1.Signature) []byte { 64 rBytes := sig.R.Bytes() 65 sBytes := sig.S.Bytes() 66 sigBytes := make([]byte, 64) 67 // 0 pad the byte arrays from the left if they aren't big enough. 68 copy(sigBytes[32-len(rBytes):32], rBytes) 69 copy(sigBytes[64-len(sBytes):64], sBytes) 70 return sigBytes 71 }