github.com/klaytn/klaytn@v1.10.2/crypto/crypto.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2014 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from crypto/crypto.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package crypto
    22  
    23  import (
    24  	"crypto/ecdsa"
    25  	"crypto/elliptic"
    26  	"crypto/rand"
    27  	"encoding/hex"
    28  	"errors"
    29  	"fmt"
    30  	"io"
    31  	"io/ioutil"
    32  	"math/big"
    33  	"os"
    34  
    35  	"github.com/klaytn/klaytn/common"
    36  	"github.com/klaytn/klaytn/common/math"
    37  	"github.com/klaytn/klaytn/crypto/sha3"
    38  	"github.com/klaytn/klaytn/rlp"
    39  )
    40  
    41  // SignatureLength indicates the byte length required to carry a signature with recovery id.
    42  const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id
    43  
    44  // RecoveryIDOffset points to the byte offset within the signature that contains the recovery id.
    45  const RecoveryIDOffset = 64
    46  
    47  // DigestLength sets the signature digest exact length
    48  const DigestLength = 32
    49  
    50  var (
    51  	secp256k1N, _  = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
    52  	secp256k1halfN = new(big.Int).Div(secp256k1N, common.Big2)
    53  )
    54  
    55  var errInvalidPubkey = errors.New("invalid secp256k1 public key")
    56  
    57  // Keccak256 calculates and returns the Keccak256 hash of the input data.
    58  func Keccak256(data ...[]byte) []byte {
    59  	d := sha3.NewKeccak256()
    60  	for _, b := range data {
    61  		d.Write(b)
    62  	}
    63  	return d.Sum(nil)
    64  }
    65  
    66  // Keccak256Hash calculates and returns the Keccak256 hash of the input data,
    67  // converting it to an internal Hash data structure.
    68  func Keccak256Hash(data ...[]byte) (h common.Hash) {
    69  	d := sha3.NewKeccak256()
    70  	for _, b := range data {
    71  		d.Write(b)
    72  	}
    73  	d.Sum(h[:0])
    74  	return h
    75  }
    76  
    77  // Keccak512 calculates and returns the Keccak512 hash of the input data.
    78  func Keccak512(data ...[]byte) []byte {
    79  	d := sha3.NewKeccak512()
    80  	for _, b := range data {
    81  		d.Write(b)
    82  	}
    83  	return d.Sum(nil)
    84  }
    85  
    86  // CreateAddress creates a Klaytn address given the bytes and the nonce
    87  func CreateAddress(b common.Address, nonce uint64) common.Address {
    88  	data, _ := rlp.EncodeToBytes(struct {
    89  		Addr  common.Address
    90  		Nonce uint64
    91  	}{b, nonce})
    92  	return common.BytesToAddress(Keccak256(data)[12:])
    93  }
    94  
    95  // CreateAddress2 creates a Klaytn address given the address bytes, initial
    96  // contract code hash and a salt.
    97  func CreateAddress2(b common.Address, salt [32]byte, inithash []byte) common.Address {
    98  	return common.BytesToAddress(Keccak256([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:])
    99  }
   100  
   101  // ToECDSA creates a private key with the given D value.
   102  func ToECDSA(d []byte) (*ecdsa.PrivateKey, error) {
   103  	return toECDSA(d, true)
   104  }
   105  
   106  // ToECDSAUnsafe blindly converts a binary blob to a private key. It should almost
   107  // never be used unless you are sure the input is valid and want to avoid hitting
   108  // errors due to bad origin encoding (0 prefixes cut off).
   109  func ToECDSAUnsafe(d []byte) *ecdsa.PrivateKey {
   110  	priv, _ := toECDSA(d, false)
   111  	return priv
   112  }
   113  
   114  // toECDSA creates a private key with the given D value. The strict parameter
   115  // controls whether the key's length should be enforced at the curve size or
   116  // it can also accept legacy encodings (0 prefixes).
   117  func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) {
   118  	priv := new(ecdsa.PrivateKey)
   119  	priv.PublicKey.Curve = S256()
   120  	if strict && 8*len(d) != priv.Params().BitSize {
   121  		return nil, fmt.Errorf("invalid length, need %d bits", priv.Params().BitSize)
   122  	}
   123  	priv.D = new(big.Int).SetBytes(d)
   124  
   125  	// The priv.D must < N
   126  	if priv.D.Cmp(secp256k1N) >= 0 {
   127  		return nil, fmt.Errorf("invalid private key, >=N")
   128  	}
   129  	// The priv.D must not be zero or negative.
   130  	if priv.D.Sign() <= 0 {
   131  		return nil, fmt.Errorf("invalid private key, zero or negative")
   132  	}
   133  
   134  	priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d)
   135  	if priv.PublicKey.X == nil {
   136  		return nil, errors.New("invalid private key")
   137  	}
   138  	return priv, nil
   139  }
   140  
   141  // FromECDSA exports a private key into a binary dump.
   142  func FromECDSA(priv *ecdsa.PrivateKey) []byte {
   143  	if priv == nil {
   144  		return nil
   145  	}
   146  	return math.PaddedBigBytes(priv.D, priv.Params().BitSize/8)
   147  }
   148  
   149  // UnmarshalPubkey converts bytes to a secp256k1 public key.
   150  func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) {
   151  	x, y := elliptic.Unmarshal(S256(), pub)
   152  	if x == nil {
   153  		return nil, errInvalidPubkey
   154  	}
   155  	return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
   156  }
   157  
   158  func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
   159  	if pub == nil || pub.X == nil || pub.Y == nil {
   160  		return nil
   161  	}
   162  	return elliptic.Marshal(S256(), pub.X, pub.Y)
   163  }
   164  
   165  // HexToECDSA parses a secp256k1 private key.
   166  func HexToECDSA(hexkey string) (*ecdsa.PrivateKey, error) {
   167  	b, err := hex.DecodeString(hexkey)
   168  	if err != nil {
   169  		return nil, errors.New("invalid hex string")
   170  	}
   171  	return ToECDSA(b)
   172  }
   173  
   174  // LoadECDSA loads a secp256k1 private key from the given file.
   175  func LoadECDSA(file string) (*ecdsa.PrivateKey, error) {
   176  	buf := make([]byte, 64)
   177  	fd, err := os.Open(file)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	defer fd.Close()
   182  	if _, err := io.ReadFull(fd, buf); err != nil {
   183  		return nil, err
   184  	}
   185  
   186  	key, err := hex.DecodeString(string(buf))
   187  	if err != nil {
   188  		return nil, err
   189  	}
   190  	return ToECDSA(key)
   191  }
   192  
   193  // SaveECDSA saves a secp256k1 private key to the given file with
   194  // restrictive permissions. The key data is saved hex-encoded.
   195  func SaveECDSA(file string, key *ecdsa.PrivateKey) error {
   196  	k := hex.EncodeToString(FromECDSA(key))
   197  	return ioutil.WriteFile(file, []byte(k), 0o600)
   198  }
   199  
   200  func GenerateKey() (*ecdsa.PrivateKey, error) {
   201  	return ecdsa.GenerateKey(S256(), rand.Reader)
   202  }
   203  
   204  // ValidateSignatureValues verifies whether the signature values are valid with
   205  // the given chain rules. The v value is assumed to be either 0 or 1.
   206  func ValidateSignatureValues(v byte, r, s *big.Int, homestead bool) bool {
   207  	if r.Cmp(common.Big1) < 0 || s.Cmp(common.Big1) < 0 {
   208  		return false
   209  	}
   210  	// reject upper range of s values (ECDSA malleability)
   211  	// see discussion in secp256k1/libsecp256k1/include/secp256k1.h
   212  	if homestead && s.Cmp(secp256k1halfN) > 0 {
   213  		return false
   214  	}
   215  	// Frontier: allow s to be in full N range
   216  	return r.Cmp(secp256k1N) < 0 && s.Cmp(secp256k1N) < 0 && (v == 0 || v == 1)
   217  }
   218  
   219  func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
   220  	pubBytes := FromECDSAPub(&p)
   221  	return common.BytesToAddress(Keccak256(pubBytes[1:])[12:])
   222  }
   223  
   224  func zeroBytes(bytes []byte) {
   225  	for i := range bytes {
   226  		bytes[i] = 0
   227  	}
   228  }