github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/crypto/signature_nocgo.go (about)

     1  //go:build nacl || js || nocgo
     2  // +build nacl js nocgo
     3  
     4  package crypto
     5  
     6  import (
     7  	"crypto/ecdsa"
     8  	"crypto/elliptic"
     9  	"errors"
    10  	"fmt"
    11  	"math/big"
    12  
    13  	"github.com/btcsuite/btcd/btcec"
    14  )
    15  
    16  func Ecrecover(hash, sig []byte) ([]byte, error) {
    17  	pub, err := SigToPub(hash, sig)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	bytes := (*btcec.PublicKey)(pub).SerializeUncompressed()
    22  	return bytes, err
    23  }
    24  
    25  func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
    26  	btcsig := make([]byte, 65)
    27  	btcsig[0] = sig[64] + 27
    28  	copy(btcsig[1:], sig)
    29  
    30  	pub, _, err := btcec.RecoverCompact(btcec.S256(), btcsig, hash)
    31  	return (*ecdsa.PublicKey)(pub), err
    32  }
    33  
    34  func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) {
    35  	if len(hash) != 32 {
    36  		return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
    37  	}
    38  	if prv.Curve != btcec.S256() {
    39  		return nil, fmt.Errorf("private key curve is not secp256k1")
    40  	}
    41  	sig, err := btcec.SignCompact(btcec.S256(), (*btcec.PrivateKey)(prv), hash, false)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	v := sig[0] - 27
    46  	copy(sig, sig[1:])
    47  	sig[64] = v
    48  	return sig, nil
    49  }
    50  
    51  func VerifySignature(pubkey, hash, signature []byte) bool {
    52  	if len(signature) != 64 {
    53  		return false
    54  	}
    55  	sig := &btcec.Signature{R: new(big.Int).SetBytes(signature[:32]), S: new(big.Int).SetBytes(signature[32:])}
    56  	key, err := btcec.ParsePubKey(pubkey, btcec.S256())
    57  	if err != nil {
    58  		return false
    59  	}
    60  	if sig.S.Cmp(secp256k1_halfN) > 0 {
    61  		return false
    62  	}
    63  	return sig.Verify(hash, key)
    64  }
    65  
    66  func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {
    67  	if len(pubkey) != 33 {
    68  		return nil, errors.New("invalid compressed public key length")
    69  	}
    70  	key, err := btcec.ParsePubKey(pubkey, btcec.S256())
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	return key.ToECDSA(), nil
    75  }
    76  
    77  func CompressPubkey(pubkey *ecdsa.PublicKey) []byte {
    78  	return (*btcec.PublicKey)(pubkey).SerializeCompressed()
    79  }
    80  
    81  func S256() elliptic.Curve {
    82  	return btcec.S256()
    83  }