github.com/turingchain2020/turingchain@v1.1.21/wallet/bipwallet/go-bip32/bip32.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 A fully compliant implementation of the BIP0032 spec for Hierarchical Deterministic Bitcoin addresses 6 package bip32 7 8 import ( 9 "bytes" 10 "crypto/hmac" 11 "crypto/rand" 12 "crypto/sha512" 13 "encoding/hex" 14 "errors" 15 ) 16 17 const ( 18 // FirstHardenedChild FirstHardenedChild 19 FirstHardenedChild = uint32(0x80000000) 20 // PublicKeyCompressedLength 公钥压缩长度 21 PublicKeyCompressedLength = 33 22 ) 23 24 var ( 25 // PrivateWalletVersion 私钥钱包版本 26 PrivateWalletVersion, _ = hex.DecodeString("0488ADE4") 27 // PublicWalletVersion 公钥钱包版本 28 PublicWalletVersion, _ = hex.DecodeString("0488B21E") 29 ) 30 31 // Key Represents a bip32 extended key containing key data, chain code, parent information, and other meta data 32 type Key struct { 33 Version []byte // 4 bytes 34 Depth byte // 1 bytes 35 ChildNumber []byte // 4 bytes 36 FingerPrint []byte // 4 bytes 37 ChainCode []byte // 32 bytes 38 Key []byte // 33 bytes 39 IsPrivate bool // unserialized 40 } 41 42 // NewMasterKey Creates a new master extended key from a seed 43 func NewMasterKey(seed []byte) (*Key, error) { 44 // Generate key and chaincode 45 hmac := hmac.New(sha512.New, []byte("Bitcoin seed")) 46 _, err := hmac.Write(seed) 47 if err != nil { 48 return nil, err 49 } 50 intermediary := hmac.Sum(nil) 51 52 // Split it into our key and chain code 53 keyBytes := intermediary[:32] 54 chainCode := intermediary[32:] 55 56 // Validate key 57 err = validatePrivateKey(keyBytes) 58 if err != nil { 59 return nil, err 60 } 61 62 // Create the key struct 63 key := &Key{ 64 Version: PrivateWalletVersion, 65 ChainCode: chainCode, 66 Key: keyBytes, 67 Depth: 0x0, 68 ChildNumber: []byte{0x00, 0x00, 0x00, 0x00}, 69 FingerPrint: []byte{0x00, 0x00, 0x00, 0x00}, 70 IsPrivate: true, 71 } 72 73 return key, nil 74 } 75 76 // NewChildKey Derives a child key from a given parent as outlined by bip32 77 func (key *Key) NewChildKey(childIdx uint32) (*Key, error) { 78 hardenedChild := childIdx >= FirstHardenedChild 79 childIndexBytes := uint32Bytes(childIdx) 80 81 // Fail early if trying to create hardned child from public key 82 if !key.IsPrivate && hardenedChild { 83 return nil, errors.New("Can't create hardened child for public key") 84 } 85 86 // Get intermediary to create key and chaincode from 87 // Hardened children are based on the private key 88 // NonHardened children are based on the public key 89 var data []byte 90 if hardenedChild { 91 data = append([]byte{0x0}, key.Key...) 92 } else if key.IsPrivate { 93 data = publicKeyForPrivateKey(key.Key) 94 } else { 95 data = key.Key 96 } 97 data = append(data, childIndexBytes...) 98 99 hmac := hmac.New(sha512.New, key.ChainCode) 100 _, err := hmac.Write(data) 101 if err != nil { 102 return nil, err 103 } 104 intermediary := hmac.Sum(nil) 105 106 // Create child Key with data common to all both scenarios 107 childKey := &Key{ 108 ChildNumber: childIndexBytes, 109 ChainCode: intermediary[32:], 110 Depth: key.Depth + 1, 111 IsPrivate: key.IsPrivate, 112 } 113 114 // Bip32 CKDpriv 115 if key.IsPrivate { 116 childKey.Version = PrivateWalletVersion 117 childKey.FingerPrint = hash160(publicKeyForPrivateKey(key.Key))[:4] 118 childKey.Key = addPrivateKeys(intermediary[:32], key.Key) 119 120 // Validate key 121 err := validatePrivateKey(childKey.Key) 122 if err != nil { 123 return nil, err 124 } 125 // Bip32 CKDpub 126 } else { 127 keyBytes := publicKeyForPrivateKey(intermediary[:32]) 128 // Validate key 129 err := validateChildPublicKey(keyBytes) 130 if err != nil { 131 return nil, err 132 } 133 134 childKey.Version = PublicWalletVersion 135 childKey.FingerPrint = hash160(key.Key)[:4] 136 childKey.Key = addPublicKeys(keyBytes, key.Key) 137 } 138 139 return childKey, nil 140 } 141 142 // PublicKey Create public version of key or return a copy; 'Neuter' function from the bip32 spec 143 func (key *Key) PublicKey() *Key { 144 keyBytes := key.Key 145 146 if key.IsPrivate { 147 keyBytes = publicKeyForPrivateKey(keyBytes) 148 } 149 150 return &Key{ 151 Version: PublicWalletVersion, 152 Key: keyBytes, 153 Depth: key.Depth, 154 ChildNumber: key.ChildNumber, 155 FingerPrint: key.FingerPrint, 156 ChainCode: key.ChainCode, 157 IsPrivate: false, 158 } 159 } 160 161 // Serialize Serialized an Key to a 78 byte byte slice 162 func (key *Key) Serialize() []byte { 163 // Private keys should be prepended with a single null byte 164 keyBytes := key.Key 165 if key.IsPrivate { 166 keyBytes = append([]byte{0x0}, keyBytes...) 167 } 168 169 // Write fields to buffer in order 170 buffer := new(bytes.Buffer) 171 _, err := buffer.Write(key.Version) 172 if err != nil { 173 return nil 174 } 175 err = buffer.WriteByte(key.Depth) 176 if err != nil { 177 return nil 178 } 179 _, err = buffer.Write(key.FingerPrint) 180 if err != nil { 181 return nil 182 } 183 _, err = buffer.Write(key.ChildNumber) 184 if err != nil { 185 return nil 186 } 187 _, err = buffer.Write(key.ChainCode) 188 if err != nil { 189 return nil 190 } 191 _, err = buffer.Write(keyBytes) 192 if err != nil { 193 return nil 194 } 195 196 // Append the standard doublesha256 checksum 197 serializedKey := addChecksumToBytes(buffer.Bytes()) 198 199 return serializedKey 200 } 201 202 // String Encode the Key in the standard Bitcoin base58 encoding 203 func (key *Key) String() string { 204 return string(base58Encode(key.Serialize())) 205 } 206 207 // NewSeed Cryptographically secure seed 208 func NewSeed() ([]byte, error) { 209 // Well that easy, just make go read 256 random bytes into a slice 210 s := make([]byte, 256) 211 _, err := rand.Read(s) 212 return s, err 213 }