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
This commit is contained in:
committed by
Jeffrey Wilcke
parent
bf21549faa
commit
9b0af51386
@@ -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 {
|
||||
|
Reference in New Issue
Block a user