gitlab.com/aquachain/aquachain@v1.17.16-rc3.0.20221018032414-e3ddf1e1c055/crypto/signature_nocgo.go (about) 1 // Copyright 2018 The aquachain Authors 2 // This file is part of the aquachain library. 3 // 4 // The aquachain library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The aquachain library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the aquachain library. If not, see <http://www.gnu.org/licenses/>. 16 17 package crypto 18 19 import ( 20 "crypto/ecdsa" 21 "crypto/elliptic" 22 "errors" 23 "fmt" 24 "math/big" 25 26 "github.com/btcsuite/btcd/btcec" 27 ) 28 29 // Ecrecover returns the uncompressed public key that created the given signature. 30 func Ecrecover(hash, sig []byte) ([]byte, error) { 31 pub, err := SigToPub(hash, sig) 32 if err != nil { 33 return nil, err 34 } 35 bytes := (*btcec.PublicKey)(pub).SerializeUncompressed() 36 return bytes, err 37 } 38 39 // SigToPub returns the public key that created the given signature. 40 func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { 41 // Convert to btcec input format with 'recovery id' v at the beginning. 42 btcsig := make([]byte, 65) 43 btcsig[0] = sig[64] + 27 44 copy(btcsig[1:], sig) 45 46 pub, _, err := btcec.RecoverCompact(btcec.S256(), btcsig, hash) 47 return (*ecdsa.PublicKey)(pub), err 48 } 49 50 // Sign calculates an ECDSA signature. 51 // 52 // This function is susceptible to chosen plaintext attacks that can leak 53 // information about the private key that is used for signing. Callers must 54 // be aware that the given hash cannot be chosen by an adversery. Common 55 // solution is to hash any input before calculating the signature. 56 // 57 // The produced signature is in the [R || S || V] format where V is 0 or 1. 58 func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) { 59 if len(hash) != 32 { 60 return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash)) 61 } 62 if prv.Curve != btcec.S256() { 63 return nil, fmt.Errorf("private key curve is not secp256k1") 64 } 65 sig, err := btcec.SignCompact(btcec.S256(), (*btcec.PrivateKey)(prv), hash, false) 66 if err != nil { 67 return nil, err 68 } 69 // Convert to Ethereum signature format with 'recovery id' v at the end. 70 v := sig[0] - 27 71 copy(sig, sig[1:]) 72 sig[64] = v 73 return sig, nil 74 } 75 76 // VerifySignature checks that the given public key created signature over hash. 77 // The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. 78 // The signature should have the 64 byte [R || S] format. 79 func VerifySignature(pubkey, hash, signature []byte) bool { 80 if len(signature) != 64 { 81 return false 82 } 83 sig := &btcec.Signature{R: new(big.Int).SetBytes(signature[:32]), S: new(big.Int).SetBytes(signature[32:])} 84 key, err := btcec.ParsePubKey(pubkey, btcec.S256()) 85 if err != nil { 86 return false 87 } 88 // Reject malleable signatures. libsecp256k1 does this check but btcec doesn't. 89 if sig.S.Cmp(secp256k1_halfN) > 0 { 90 return false 91 } 92 return sig.Verify(hash, key) 93 } 94 95 // DecompressPubkey parses a public key in the 33-byte compressed format. 96 func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) { 97 if len(pubkey) != 33 { 98 return nil, errors.New("invalid compressed public key length") 99 } 100 key, err := btcec.ParsePubKey(pubkey, btcec.S256()) 101 if err != nil { 102 return nil, err 103 } 104 return key.ToECDSA(), nil 105 } 106 107 // CompressPubkey encodes a public key to the 33-byte compressed format. 108 func CompressPubkey(pubkey *ecdsa.PublicKey) []byte { 109 return (*btcec.PublicKey)(pubkey).SerializeCompressed() 110 } 111 112 // S256 returns an instance of the secp256k1 curve. 113 func S256() elliptic.Curve { 114 return btcec.S256() 115 }