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 }