github.com/turingchain2020/turingchain@v1.1.21/wallet/bipwallet/go-bip32/utils.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bip32 6 7 import ( 8 "bytes" 9 "crypto/sha256" 10 "encoding/binary" 11 "errors" 12 "fmt" 13 "math/big" 14 15 "io" 16 17 "github.com/turingchain2020/turingchain/wallet/bipwallet/basen" 18 btcutil "github.com/turingchain2020/turingchain/wallet/bipwallet/btcutilecc" 19 "golang.org/x/crypto/ripemd160" 20 ) 21 22 var ( 23 curve = btcutil.Secp256k1() 24 curveParams = curve.Params() 25 bitcoinBase58Encoding = basen.NewEncoding("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") 26 ) 27 28 // 29 // Hashes 30 // 31 32 func hashSha256(data []byte) []byte { 33 hasher := sha256.New() 34 _, err := hasher.Write(data) 35 if err != nil { 36 return nil 37 } 38 return hasher.Sum(nil) 39 } 40 41 func hashDoubleSha256(data []byte) []byte { 42 return hashSha256(hashSha256(data)) 43 } 44 45 func hashRipeMD160(data []byte) []byte { 46 hasher := ripemd160.New() 47 _, err := io.WriteString(hasher, string(data)) 48 if err != nil { 49 return nil 50 } 51 return hasher.Sum(nil) 52 } 53 54 func hash160(data []byte) []byte { 55 return hashRipeMD160(hashSha256(data)) 56 } 57 58 // 59 // Encoding 60 // 61 62 func checksum(data []byte) []byte { 63 return hashDoubleSha256(data)[:4] 64 } 65 66 func addChecksumToBytes(data []byte) []byte { 67 checksum := checksum(data) 68 return append(data, checksum...) 69 } 70 71 func base58Encode(data []byte) []byte { 72 return []byte(bitcoinBase58Encoding.EncodeToString(data)) 73 } 74 75 // Keys 76 func publicKeyForPrivateKey(key []byte) []byte { 77 return compressPublicKey(curve.ScalarBaseMult(key)) 78 } 79 80 func addPublicKeys(key1 []byte, key2 []byte) []byte { 81 x1, y1 := expandPublicKey(key1) 82 x2, y2 := expandPublicKey(key2) 83 return compressPublicKey(curve.Add(x1, y1, x2, y2)) 84 } 85 86 func addPrivateKeys(key1 []byte, key2 []byte) []byte { 87 var key1Int big.Int 88 var key2Int big.Int 89 key1Int.SetBytes(key1) 90 key2Int.SetBytes(key2) 91 92 key1Int.Add(&key1Int, &key2Int) 93 key1Int.Mod(&key1Int, curve.Params().N) 94 95 b := key1Int.Bytes() 96 if len(b) < 32 { 97 extra := make([]byte, 32-len(b)) 98 b = append(extra, b...) 99 } 100 return b 101 } 102 103 func compressPublicKey(x *big.Int, y *big.Int) []byte { 104 var key bytes.Buffer 105 106 // Write header; 0x2 for even y value; 0x3 for odd 107 err := key.WriteByte(byte(0x2) + byte(y.Bit(0))) 108 if err != nil { 109 return nil 110 } 111 112 // Write X coord; Pad the key so x is aligned with the LSB. Pad size is key length - header size (1) - xBytes size 113 xBytes := x.Bytes() 114 for i := 0; i < (PublicKeyCompressedLength - 1 - len(xBytes)); i++ { 115 err := key.WriteByte(0x0) 116 if err != nil { 117 return nil 118 } 119 } 120 _, err = key.Write(xBytes) 121 if err != nil { 122 return nil 123 } 124 return key.Bytes() 125 } 126 127 func expandPublicKey(key []byte) (*big.Int, *big.Int) { 128 params := curveParams 129 exp := big.NewInt(1) 130 exp.Add(params.P, exp) 131 exp.Div(exp, big.NewInt(4)) 132 x := big.NewInt(0).SetBytes(key[1:33]) 133 y := big.NewInt(0).SetBytes(key[:1]) 134 beta := big.NewInt(0) 135 // #nosec 136 beta.Exp(x, big.NewInt(3), nil) 137 beta.Add(beta, big.NewInt(7)) 138 // #nosec 139 beta.Exp(beta, exp, params.P) 140 if y.Add(beta, y).Mod(y, big.NewInt(2)).Int64() == 0 { 141 y = beta 142 } else { 143 y = beta.Sub(params.P, beta) 144 } 145 return x, y 146 } 147 148 func validatePrivateKey(key []byte) error { 149 if fmt.Sprintf("%x", key) == "0000000000000000000000000000000000000000000000000000000000000000" || //if the key is zero 150 bytes.Compare(key, curveParams.N.Bytes()) >= 0 || //or is outside of the curve 151 len(key) != 32 { //or is too short 152 return errors.New("Invalid seed") 153 } 154 155 return nil 156 } 157 158 func validateChildPublicKey(key []byte) error { 159 x, y := expandPublicKey(key) 160 161 if x.Sign() == 0 || y.Sign() == 0 { 162 return errors.New("Invalid public key") 163 } 164 165 return nil 166 } 167 168 // 169 // Numerical 170 // 171 func uint32Bytes(i uint32) []byte { 172 bytes := make([]byte, 4) 173 binary.BigEndian.PutUint32(bytes, i) 174 return bytes 175 }