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  }