You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
5.4 KiB

8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
  1. package hd
  2. import (
  3. "bytes"
  4. "crypto/hmac"
  5. "crypto/sha512"
  6. "encoding/binary"
  7. "encoding/hex"
  8. "encoding/json"
  9. "fmt"
  10. "io/ioutil"
  11. "os"
  12. "testing"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/tyler-smith/go-bip39"
  15. "github.com/btcsuite/btcd/chaincfg"
  16. "github.com/btcsuite/btcutil/hdkeychain"
  17. "github.com/mndrix/btcutil"
  18. "github.com/tyler-smith/go-bip32"
  19. "github.com/tendermint/go-crypto"
  20. )
  21. type addrData struct {
  22. Mnemonic string
  23. Master string
  24. Seed string
  25. Priv string
  26. Pub string
  27. Addr string
  28. }
  29. // NOTE: atom fundraiser address
  30. var hdPath string = "m/44'/118'/0'/0/0"
  31. var hdToAddrTable []addrData
  32. func init() {
  33. b, err := ioutil.ReadFile("test.json")
  34. if err != nil {
  35. fmt.Println(err)
  36. os.Exit(1)
  37. }
  38. err = json.Unmarshal(b, &hdToAddrTable)
  39. if err != nil {
  40. fmt.Println(err)
  41. os.Exit(1)
  42. }
  43. }
  44. func TestHDToAddr(t *testing.T) {
  45. for i, d := range hdToAddrTable {
  46. privB, _ := hex.DecodeString(d.Priv)
  47. pubB, _ := hex.DecodeString(d.Pub)
  48. addrB, _ := hex.DecodeString(d.Addr)
  49. seedB, _ := hex.DecodeString(d.Seed)
  50. masterB, _ := hex.DecodeString(d.Master)
  51. seed := bip39.NewSeed(d.Mnemonic, "")
  52. fmt.Println("================================")
  53. fmt.Println("ROUND:", i, "MNEMONIC:", d.Mnemonic)
  54. // master, priv, pub := tylerSmith(seed)
  55. // master, priv, pub := btcsuite(seed)
  56. master, priv, pub := gocrypto(seed)
  57. fmt.Printf("\tNODEJS GOLANG\n")
  58. fmt.Printf("SEED \t%X %X\n", seedB, seed)
  59. fmt.Printf("MSTR \t%X %X\n", masterB, master)
  60. fmt.Printf("PRIV \t%X %X\n", privB, priv)
  61. fmt.Printf("PUB \t%X %X\n", pubB, pub)
  62. _, _ = priv, privB
  63. assert.Equal(t, master, masterB, fmt.Sprintf("Expected masters to match for %d", i))
  64. assert.Equal(t, priv, privB, "Expected priv keys to match")
  65. assert.Equal(t, pub, pubB, fmt.Sprintf("Expected pub keys to match for %d", i))
  66. var pubT crypto.PubKeySecp256k1
  67. copy(pubT[:], pub)
  68. addr := pubT.Address()
  69. fmt.Printf("ADDR \t%X %X\n", addrB, addr)
  70. assert.Equal(t, addr, addrB, fmt.Sprintf("Expected addresses to match %d", i))
  71. }
  72. }
  73. func TestReverseBytes(t *testing.T) {
  74. tests := [...]struct {
  75. v []byte
  76. want []byte
  77. }{
  78. {[]byte(""), []byte("")},
  79. {nil, nil},
  80. {[]byte("Tendermint"), []byte("tnimredneT")},
  81. {[]byte("T"), []byte("T")},
  82. {[]byte("Te"), []byte("eT")},
  83. }
  84. for i, tt := range tests {
  85. got := ReverseBytes(tt.v)
  86. if !bytes.Equal(got, tt.want) {
  87. t.Errorf("#%d:\ngot= (%x)\nwant=(%x)", i, got, tt.want)
  88. }
  89. }
  90. }
  91. func ifExit(err error, n int) {
  92. if err != nil {
  93. fmt.Println(n, err)
  94. os.Exit(1)
  95. }
  96. }
  97. func gocrypto(seed []byte) ([]byte, []byte, []byte) {
  98. _, priv, ch, _ := ComputeMastersFromSeed(string(seed))
  99. privBytes := DerivePrivateKeyForPath(
  100. HexDecode(priv),
  101. HexDecode(ch),
  102. "44'/118'/0'/0/0",
  103. )
  104. pubBytes := PubKeyBytesFromPrivKeyBytes(privBytes, true)
  105. return HexDecode(priv), privBytes, pubBytes
  106. }
  107. func btcsuite(seed []byte) ([]byte, []byte, []byte) {
  108. fmt.Println("HD")
  109. masterKey, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams)
  110. if err != nil {
  111. hmac := hmac.New(sha512.New, []byte("Bitcoin seed"))
  112. hmac.Write([]byte(seed))
  113. intermediary := hmac.Sum(nil)
  114. curve := btcutil.Secp256k1()
  115. curveParams := curve.Params()
  116. // Split it into our key and chain code
  117. keyBytes := intermediary[:32]
  118. fmt.Printf("\t%X\n", keyBytes)
  119. fmt.Printf("\t%X\n", curveParams.N.Bytes())
  120. keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes))
  121. fmt.Printf("\t%d\n", keyInt)
  122. }
  123. fh := hdkeychain.HardenedKeyStart
  124. k, err := masterKey.Child(uint32(fh + 44))
  125. ifExit(err, 44)
  126. k, err = k.Child(uint32(fh + 118))
  127. ifExit(err, 118)
  128. k, err = k.Child(uint32(fh + 0))
  129. ifExit(err, 1)
  130. k, err = k.Child(uint32(0))
  131. ifExit(err, 2)
  132. k, err = k.Child(uint32(0))
  133. ifExit(err, 3)
  134. ecpriv, err := k.ECPrivKey()
  135. ifExit(err, 10)
  136. ecpub, err := k.ECPubKey()
  137. ifExit(err, 11)
  138. priv := ecpriv.Serialize()
  139. pub := ecpub.SerializeCompressed()
  140. mkey, _ := masterKey.ECPrivKey()
  141. return mkey.Serialize(), priv, pub
  142. }
  143. // return priv and pub
  144. func tylerSmith(seed []byte) ([]byte, []byte, []byte) {
  145. masterKey, err := bip32.NewMasterKey(seed)
  146. if err != nil {
  147. hmac := hmac.New(sha512.New, []byte("Bitcoin seed"))
  148. hmac.Write([]byte(seed))
  149. intermediary := hmac.Sum(nil)
  150. curve := btcutil.Secp256k1()
  151. curveParams := curve.Params()
  152. // Split it into our key and chain code
  153. keyBytes := intermediary[:32]
  154. fmt.Printf("\t%X\n", keyBytes)
  155. fmt.Printf("\t%X\n", curveParams.N.Bytes())
  156. keyInt, _ := binary.ReadVarint(bytes.NewBuffer(keyBytes))
  157. fmt.Printf("\t%d\n", keyInt)
  158. }
  159. ifExit(err, 0)
  160. fh := bip32.FirstHardenedChild
  161. k, err := masterKey.NewChildKey(fh + 44)
  162. ifExit(err, 44)
  163. k, err = k.NewChildKey(fh + 118)
  164. ifExit(err, 118)
  165. k, err = k.NewChildKey(fh + 0)
  166. ifExit(err, 1)
  167. k, err = k.NewChildKey(0)
  168. ifExit(err, 2)
  169. k, err = k.NewChildKey(0)
  170. ifExit(err, 3)
  171. priv := k.Key
  172. pub := k.PublicKey().Key
  173. return masterKey.Key, priv, pub
  174. }
  175. // Benchmarks
  176. var revBytesCases = [][]byte{
  177. nil,
  178. []byte(""),
  179. []byte("12"),
  180. // 16byte case
  181. []byte("abcdefghijklmnop"),
  182. // 32byte case
  183. []byte("abcdefghijklmnopqrstuvwxyz123456"),
  184. // 64byte case
  185. []byte("abcdefghijklmnopqrstuvwxyz123456abcdefghijklmnopqrstuvwxyz123456"),
  186. }
  187. func BenchmarkReverseBytes(b *testing.B) {
  188. var sink []byte
  189. for i := 0; i < b.N; i++ {
  190. for _, tt := range revBytesCases {
  191. sink = ReverseBytes(tt)
  192. }
  193. }
  194. b.ReportAllocs()
  195. // sink is necessary to ensure if the compiler tries
  196. // to smart, that it won't optimize away the benchmarks.
  197. if sink != nil {
  198. }
  199. }