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  }