github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/crypto/secp256k1/secp256k1_nocgo.go (about)

     1  //go:build !libsecp256k1
     2  
     3  package secp256k1
     4  
     5  import (
     6  	"github.com/btcsuite/btcd/btcec/v2"
     7  	"github.com/btcsuite/btcd/btcec/v2/ecdsa"
     8  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
     9  
    10  	"github.com/gnolang/gno/tm2/pkg/crypto"
    11  )
    12  
    13  // Sign creates an ECDSA signature on curve Secp256k1, using SHA256 on the msg.
    14  // The returned signature will be of the form R || S (in lower-S form).
    15  func (privKey PrivKeySecp256k1) Sign(msg []byte) ([]byte, error) {
    16  	priv, _ := btcec.PrivKeyFromBytes(privKey[:])
    17  
    18  	sig, err := ecdsa.SignCompact(priv, crypto.Sha256(msg), false) // ref uncompressed pubkey
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	// remove compact sig recovery code byte at the beginning
    24  	return sig[1:], nil
    25  }
    26  
    27  // VerifyBytes verifies a signature of the form R || S.
    28  // It rejects signatures which are not in lower-S form.
    29  func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sigStr []byte) bool {
    30  	if len(sigStr) != 64 {
    31  		return false
    32  	}
    33  
    34  	pub, err := secp256k1.ParsePubKey(pubKey[:])
    35  	if err != nil {
    36  		return false
    37  	}
    38  
    39  	psig, ok := signatureFromBytes(sigStr)
    40  	if !ok {
    41  		return false
    42  	}
    43  
    44  	return psig.Verify(crypto.Sha256(msg), pub)
    45  }
    46  
    47  // Read Signature struct from R || S. Caller needs to ensure
    48  // that len(sigStr) == 64.
    49  func signatureFromBytes(sigStr []byte) (*ecdsa.Signature, bool) {
    50  	// parse the signature:
    51  	var r, s secp256k1.ModNScalar
    52  	if r.SetByteSlice(sigStr[:32]) {
    53  		return nil, false // overflow
    54  	}
    55  	if s.SetByteSlice(sigStr[32:]) {
    56  		return nil, false
    57  	}
    58  
    59  	// Reject malleable signatures. libsecp256k1 does this check but btcec doesn't.
    60  	if s.IsOverHalfOrder() {
    61  		return nil, false
    62  	}
    63  
    64  	return ecdsa.NewSignature(&r, &s), true
    65  }