github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/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 }