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  }