diff options
author | Felix Lange <fjl@users.noreply.github.com> | 2017-02-18 16:24:12 +0800 |
---|---|---|
committer | Jeffrey Wilcke <jeffrey@ethereum.org> | 2017-02-18 16:24:12 +0800 |
commit | 9b0af513867fad4aeb3516e4711dd0ea4f5bc90c (patch) | |
tree | b37d808d57873c6aec550431534e26602dfd0475 /crypto/crypto.go | |
parent | bf21549faa7de6e2b920855468b14856c6f503c4 (diff) | |
download | dexon-9b0af513867fad4aeb3516e4711dd0ea4f5bc90c.tar.gz dexon-9b0af513867fad4aeb3516e4711dd0ea4f5bc90c.tar.zst dexon-9b0af513867fad4aeb3516e4711dd0ea4f5bc90c.zip |
crypto: add btcec fallback for sign/recover without cgo (#3680)
* vendor: add github.com/btcsuite/btcd/btcec
* crypto: add btcec fallback for sign/recover without cgo
This commit adds a non-cgo fallback implementation of secp256k1
operations.
* crypto, core/vm: remove wrappers for sha256, ripemd160
Diffstat (limited to 'crypto/crypto.go')
-rw-r--r-- | crypto/crypto.go | 95 |
1 files changed, 16 insertions, 79 deletions
diff --git a/crypto/crypto.go b/crypto/crypto.go index ce45ebd38..9d67d82e1 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -20,22 +20,21 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" - "crypto/sha256" - "fmt" + "encoding/hex" + "errors" "io" "io/ioutil" "math/big" "os" - "encoding/hex" - "errors" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto/ecies" - "github.com/ethereum/go-ethereum/crypto/secp256k1" "github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/rlp" - "golang.org/x/crypto/ripemd160" +) + +var ( + secp256k1_N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) + secp256k1_halfN = new(big.Int).Div(secp256k1_N, big.NewInt(2)) ) func Keccak256(data ...[]byte) []byte { @@ -56,7 +55,6 @@ func Keccak256Hash(data ...[]byte) (h common.Hash) { } // Deprecated: For backward compatibility as other packages depend on these -func Sha3(data ...[]byte) []byte { return Keccak256(data...) } func Sha3Hash(data ...[]byte) common.Hash { return Keccak256Hash(data...) } // Creates an ethereum address given the bytes and the nonce @@ -65,39 +63,16 @@ func CreateAddress(b common.Address, nonce uint64) common.Address { return common.BytesToAddress(Keccak256(data)[12:]) } -func Sha256(data []byte) []byte { - hash := sha256.Sum256(data) - - return hash[:] -} - -func Ripemd160(data []byte) []byte { - ripemd := ripemd160.New() - ripemd.Write(data) - - return ripemd.Sum(nil) -} - -// Ecrecover returns the public key for the private key that was used to -// calculate the signature. -// -// Note: secp256k1 expects the recover id to be either 0, 1. Ethereum -// signatures have a recover id with an offset of 27. Callers must take -// this into account and if "recovering" from an Ethereum signature adjust. -func Ecrecover(hash, sig []byte) ([]byte, error) { - return secp256k1.RecoverPubkey(hash, sig) -} - -// New methods using proper ecdsa keys from the stdlib +// ToECDSA creates a private key with the given D value. func ToECDSA(prv []byte) *ecdsa.PrivateKey { if len(prv) == 0 { return nil } priv := new(ecdsa.PrivateKey) - priv.PublicKey.Curve = secp256k1.S256() + priv.PublicKey.Curve = S256() priv.D = common.BigD(prv) - priv.PublicKey.X, priv.PublicKey.Y = secp256k1.S256().ScalarBaseMult(prv) + priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(prv) return priv } @@ -112,15 +87,15 @@ func ToECDSAPub(pub []byte) *ecdsa.PublicKey { if len(pub) == 0 { return nil } - x, y := elliptic.Unmarshal(secp256k1.S256(), pub) - return &ecdsa.PublicKey{Curve: secp256k1.S256(), X: x, Y: y} + x, y := elliptic.Unmarshal(S256(), pub) + return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y} } func FromECDSAPub(pub *ecdsa.PublicKey) []byte { if pub == nil || pub.X == nil || pub.Y == nil { return nil } - return elliptic.Marshal(secp256k1.S256(), pub.X, pub.Y) + return elliptic.Marshal(S256(), pub.X, pub.Y) } // HexToECDSA parses a secp256k1 private key. @@ -164,7 +139,7 @@ func SaveECDSA(file string, key *ecdsa.PrivateKey) error { } func GenerateKey() (*ecdsa.PrivateKey, error) { - return ecdsa.GenerateKey(secp256k1.S256(), rand.Reader) + return ecdsa.GenerateKey(S256(), rand.Reader) } // ValidateSignatureValues verifies whether the signature values are valid with @@ -175,49 +150,11 @@ func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool { } // reject upper range of s values (ECDSA malleability) // see discussion in secp256k1/libsecp256k1/include/secp256k1.h - if homestead && s.Cmp(secp256k1.HalfN) > 0 { + if homestead && s.Cmp(secp256k1_halfN) > 0 { return false } // Frontier: allow s to be in full N range - return r.Cmp(secp256k1.N) < 0 && s.Cmp(secp256k1.N) < 0 && (v == 0 || v == 1) -} - -func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) { - s, err := Ecrecover(hash, sig) - if err != nil { - return nil, err - } - - x, y := elliptic.Unmarshal(secp256k1.S256(), s) - return &ecdsa.PublicKey{Curve: secp256k1.S256(), X: x, Y: y}, nil -} - -// Sign calculates an ECDSA signature. -// -// This function is susceptible to chosen plaintext attacks that can leak -// information about the private key that is used for signing. Callers must -// be aware that the given hash cannot be chosen by an adversery. Common -// solution is to hash any input before calculating the signature. -// -// The produced signature is in the [R || S || V] format where V is 0 or 1. -func Sign(data []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { - if len(data) != 32 { - return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(data)) - } - - seckey := common.LeftPadBytes(prv.D.Bytes(), prv.Params().BitSize/8) - defer zeroBytes(seckey) - sig, err = secp256k1.Sign(data, seckey) - return -} - -func Encrypt(pub *ecdsa.PublicKey, message []byte) ([]byte, error) { - return ecies.Encrypt(rand.Reader, ecies.ImportECDSAPublic(pub), message, nil, nil) -} - -func Decrypt(prv *ecdsa.PrivateKey, ct []byte) ([]byte, error) { - key := ecies.ImportECDSA(prv) - return key.Decrypt(rand.Reader, ct, nil, nil) + return r.Cmp(secp256k1_N) < 0 && s.Cmp(secp256k1_N) < 0 && (v == 0 || v == 1) } func PubkeyToAddress(p ecdsa.PublicKey) common.Address { |