github.com/core-coin/go-core/v2@v2.1.9/crypto/crypto.go (about)

     1  // Copyright 2023 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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 go-core 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 go-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package crypto
    18  
    19  import (
    20  	"bufio"
    21  	"encoding/hex"
    22  	"errors"
    23  	"fmt"
    24  	"hash"
    25  	"io"
    26  	"io/ioutil"
    27  	"os"
    28  
    29  	"golang.org/x/crypto/sha3"
    30  
    31  	"github.com/core-coin/go-core/v2/common"
    32  	"github.com/core-coin/go-core/v2/rlp"
    33  )
    34  
    35  type PublicKey [57]byte
    36  
    37  type PrivateKey struct {
    38  	privateKey [57]byte
    39  	publicKey  *PublicKey
    40  	address    common.Address
    41  }
    42  
    43  func (p *PrivateKey) PrivateKey() []byte {
    44  	return p.privateKey[:]
    45  }
    46  
    47  func (p *PrivateKey) PublicKey() *PublicKey {
    48  	if p.publicKey == nil {
    49  		p.publicKey = DerivePublicKey(p)
    50  	}
    51  	return p.publicKey
    52  }
    53  
    54  func (p *PrivateKey) Address() common.Address {
    55  	if p.publicKey == nil {
    56  		p.publicKey = DerivePublicKey(p)
    57  	}
    58  	if (common.Address{} == p.address) {
    59  		p.address = PubkeyToAddress(p.publicKey)
    60  	}
    61  	return p.address
    62  }
    63  
    64  const SignatureLength = 114
    65  const PubkeyLength = 57
    66  const PrivkeyLength = 57
    67  const ExtendedSignatureLength = SignatureLength + PubkeyLength
    68  
    69  var errInvalidPubkey = errors.New("invalid public key")
    70  var errInvalidPrivkey = errors.New("invalid private key")
    71  var errInvalidSignature = errors.New("invalid signature")
    72  
    73  // SHA3State wraps sha3.state. In addition to the usual hash methods, it also supports
    74  // Read to get a variable amount of data from the hash state. Read is faster than Sum
    75  // because it doesn't copy the internal state, but also modifies the internal state.
    76  type SHA3State interface {
    77  	hash.Hash
    78  	Read([]byte) (int, error)
    79  }
    80  
    81  // SHA3 calculates and returns the SHA3 hash of the input data.
    82  func SHA3(data ...[]byte) []byte {
    83  	b := make([]byte, 32)
    84  	d := sha3.New256().(SHA3State)
    85  	for _, b := range data {
    86  		d.Write(b)
    87  	}
    88  	d.Read(b)
    89  	return b
    90  }
    91  
    92  // SHA3Hash calculates and returns the SHA3 hash of the input data,
    93  // converting it to an internal Hash data structure.
    94  func SHA3Hash(data ...[]byte) (h common.Hash) {
    95  	d := sha3.New256().(SHA3State)
    96  	for _, b := range data {
    97  		d.Write(b)
    98  	}
    99  	d.Read(h[:])
   100  	return h
   101  }
   102  
   103  // Keccak512 calculates and returns the Keccak512 hash of the input data.
   104  func Keccak512(data ...[]byte) []byte {
   105  	d := sha3.NewLegacyKeccak512()
   106  	for _, b := range data {
   107  		d.Write(b)
   108  	}
   109  	return d.Sum(nil)
   110  }
   111  
   112  // CreateAddress creates an core address given the bytes and the nonce
   113  func CreateAddress(b common.Address, nonce uint64) common.Address {
   114  	data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
   115  	addr := SHA3(data)[12:]
   116  	prefix := common.DefaultNetworkID.Bytes()
   117  	checksum := common.Hex2Bytes(common.CalculateChecksum(addr, prefix))
   118  	return common.BytesToAddress(append(append(prefix, checksum...), addr...))
   119  }
   120  
   121  // CreateAddress2 creates an core address given the address bytes, initial
   122  // contract code hash and a salt.
   123  func CreateAddress2(b common.Address, salt [32]byte, inithash []byte) common.Address {
   124  	addr := SHA3([]byte{0xff}, b.Bytes(), salt[:], inithash)[12:]
   125  	prefix := common.DefaultNetworkID.Bytes()
   126  	checksum := common.Hex2Bytes(common.CalculateChecksum(addr, prefix))
   127  	return common.BytesToAddress(append(append(prefix, checksum...), addr...))
   128  }
   129  
   130  func PubkeyToAddress(p *PublicKey) common.Address {
   131  	addr := SHA3(p[:])[12:]
   132  	prefix := common.DefaultNetworkID.Bytes()
   133  	checksum := common.Hex2Bytes(common.CalculateChecksum(addr, prefix))
   134  	return common.BytesToAddress(append(append(prefix, checksum...), addr...))
   135  }
   136  
   137  // UnmarshalPrivateKey creates a private key with the given D value.
   138  func UnmarshalPrivateKey(d []byte) (*PrivateKey, error) {
   139  	if len(d) != PrivkeyLength {
   140  		return nil, errInvalidPrivkey
   141  	}
   142  	priv := PrivateKey{}
   143  	copy(priv.privateKey[:], d[:])
   144  	return &priv, nil
   145  }
   146  
   147  // UnmarshalPrivateKeyHex parses a private key.
   148  func UnmarshalPrivateKeyHex(hexkey string) (*PrivateKey, error) {
   149  	b, err := hex.DecodeString(hexkey)
   150  	if byteErr, ok := err.(hex.InvalidByteError); ok {
   151  		return nil, fmt.Errorf("invalid hex character %q in private key", byte(byteErr))
   152  	} else if err != nil {
   153  		return nil, errors.New("invalid hex data for private key")
   154  	}
   155  	return UnmarshalPrivateKey(b)
   156  }
   157  
   158  // MarshalPrivateKey exports a private key into a binary dump.
   159  func MarshalPrivateKey(priv *PrivateKey) []byte {
   160  	if priv == nil {
   161  		return nil
   162  	}
   163  	return priv.privateKey[:]
   164  }
   165  
   166  // UnmarshalPubKey converts bytes to a public key.
   167  func UnmarshalPubKey(pub []byte) (*PublicKey, error) {
   168  	if len(pub) != PubkeyLength {
   169  		return nil, errInvalidPubkey
   170  	}
   171  	p := PublicKey{}
   172  	copy(p[:], pub[:])
   173  	return &p, nil
   174  }
   175  
   176  // LoadEDDSA loads a ed448 private key from the given file.
   177  func LoadEDDSA(file string) (*PrivateKey, error) {
   178  	fd, err := os.Open(file)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	defer fd.Close()
   183  
   184  	r := bufio.NewReader(fd)
   185  	buf := make([]byte, PrivkeyLength*2)
   186  	n, err := readASCII(buf, r)
   187  	if err != nil {
   188  		return nil, err
   189  	} else if n != len(buf) {
   190  		return nil, fmt.Errorf("key file too short, want 57 hex characters")
   191  	}
   192  	if err := checkKeyFileEnd(r); err != nil {
   193  		return nil, err
   194  	}
   195  
   196  	return UnmarshalPrivateKeyHex(string(buf))
   197  }
   198  
   199  // Ecrecover returns the public key that created the given signature.
   200  func Ecrecover(hash, sig []byte) ([]byte, error) {
   201  	pubkey, err := SigToPub(hash, sig)
   202  	if err != nil {
   203  		return nil, err
   204  	}
   205  	return pubkey[:], nil
   206  }
   207  
   208  // SaveEDDSA saves a private key to the given file with
   209  // restrictive permissions. The key data is saved hex-encoded.
   210  func SaveEDDSA(file string, key *PrivateKey) error {
   211  	k := hex.EncodeToString(key.privateKey[:])
   212  	return ioutil.WriteFile(file, []byte(k), 0600)
   213  }
   214  
   215  // readASCII reads into 'buf', stopping when the buffer is full or
   216  // when a non-printable control character is encountered.
   217  func readASCII(buf []byte, r *bufio.Reader) (n int, err error) {
   218  	for ; n < len(buf); n++ {
   219  		buf[n], err = r.ReadByte()
   220  		switch {
   221  		case err == io.EOF || buf[n] < '!':
   222  			return n, nil
   223  		case err != nil:
   224  			return n, err
   225  		}
   226  	}
   227  	return n, nil
   228  }
   229  
   230  // checkKeyFileEnd skips over additional newlines at the end of a key file.
   231  func checkKeyFileEnd(r *bufio.Reader) error {
   232  	for i := 0; ; i++ {
   233  		b, err := r.ReadByte()
   234  		switch {
   235  		case err == io.EOF:
   236  			return nil
   237  		case err != nil:
   238  			return err
   239  		case b != '\n' && b != '\r':
   240  			return fmt.Errorf("invalid character %q at end of key file", b)
   241  		case i >= 2:
   242  			return errors.New("key file too long, want 57 hex characters")
   243  		}
   244  	}
   245  }
   246  
   247  func zeroBytes(bytes []byte) {
   248  	for i := range bytes {
   249  		bytes[i] = 0
   250  	}
   251  }