github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/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/franono/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 PrivKeySecp256k1) Sign(msg []byte) ([]byte, error) { 22 priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:]) 23 sig, err := priv.Sign(crypto.Sha256(msg)) 24 if err != nil { 25 return nil, err 26 } 27 sigBytes := serializeSig(sig) 28 return sigBytes, nil 29 } 30 31 // VerifyBytes verifies a signature of the form R || S. 32 // It rejects signatures which are not in lower-S form. 33 func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sigStr []byte) bool { 34 if len(sigStr) != 64 { 35 return false 36 } 37 pub, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256()) 38 if err != nil { 39 return false 40 } 41 // parse the signature: 42 signature := signatureFromBytes(sigStr) 43 // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. 44 // see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93 45 if signature.S.Cmp(secp256k1halfN) > 0 { 46 return false 47 } 48 return signature.Verify(crypto.Sha256(msg), pub) 49 } 50 51 // Read Signature struct from R || S. Caller needs to ensure 52 // that len(sigStr) == 64. 53 func signatureFromBytes(sigStr []byte) *secp256k1.Signature { 54 return &secp256k1.Signature{ 55 R: new(big.Int).SetBytes(sigStr[:32]), 56 S: new(big.Int).SetBytes(sigStr[32:64]), 57 } 58 } 59 60 // Serialize signature to R || S. 61 // R, S are padded to 32 bytes respectively. 62 func serializeSig(sig *secp256k1.Signature) []byte { 63 rBytes := sig.R.Bytes() 64 sBytes := sig.S.Bytes() 65 sigBytes := make([]byte, 64) 66 // 0 pad the byte arrays from the left if they aren't big enough. 67 copy(sigBytes[32-len(rBytes):32], rBytes) 68 copy(sigBytes[64-len(sBytes):64], sBytes) 69 return sigBytes 70 }