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