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