- // +build !libsecp256k1
-
- package secp256k1
-
- import (
- "math/big"
-
- secp256k1 "github.com/btcsuite/btcd/btcec"
-
- "github.com/tendermint/tendermint/crypto"
- )
-
- // used to reject malleable signatures
- // see:
- // - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
- // - https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/crypto.go#L39
- var secp256k1halfN = new(big.Int).Rsh(secp256k1.S256().N, 1)
-
- // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
- // The returned signature will be of the form R || S (in lower-S form).
- func (privKey PrivKey) Sign(msg []byte) ([]byte, error) {
- priv, _ := secp256k1.PrivKeyFromBytes(secp256k1.S256(), privKey[:])
- sig, err := priv.Sign(crypto.Sha256(msg))
- if err != nil {
- return nil, err
- }
- sigBytes := serializeSig(sig)
- return sigBytes, nil
- }
-
- // VerifyBytes verifies a signature of the form R || S.
- // It rejects signatures which are not in lower-S form.
- func (pubKey PubKey) VerifyBytes(msg []byte, sigStr []byte) bool {
- if len(sigStr) != 64 {
- return false
- }
- pub, err := secp256k1.ParsePubKey(pubKey[:], secp256k1.S256())
- if err != nil {
- return false
- }
- // parse the signature:
- signature := signatureFromBytes(sigStr)
- // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't.
- // see: https://github.com/ethereum/go-ethereum/blob/f9401ae011ddf7f8d2d95020b7446c17f8d98dc1/crypto/signature_nocgo.go#L90-L93
- if signature.S.Cmp(secp256k1halfN) > 0 {
- return false
- }
- return signature.Verify(crypto.Sha256(msg), pub)
- }
-
- // Read Signature struct from R || S. Caller needs to ensure
- // that len(sigStr) == 64.
- func signatureFromBytes(sigStr []byte) *secp256k1.Signature {
- return &secp256k1.Signature{
- R: new(big.Int).SetBytes(sigStr[:32]),
- S: new(big.Int).SetBytes(sigStr[32:64]),
- }
- }
-
- // Serialize signature to R || S.
- // R, S are padded to 32 bytes respectively.
- func serializeSig(sig *secp256k1.Signature) []byte {
- rBytes := sig.R.Bytes()
- sBytes := sig.S.Bytes()
- sigBytes := make([]byte, 64)
- // 0 pad the byte arrays from the left if they aren't big enough.
- copy(sigBytes[32-len(rBytes):32], rBytes)
- copy(sigBytes[64-len(sBytes):64], sBytes)
- return sigBytes
- }
|