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  }