1. 程式人生 > >golang[40]-區塊鏈-wif倒推出私鑰

golang[40]-區塊鏈-wif倒推出私鑰

wif倒推出私鑰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package main

import (
"encoding/hex"
"crypto/sha256"
"math/big"
"bytes"
"fmt"
)


//base58編碼
var b58Alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")

func Base58Encode(input []byte
)
[]byte
{

var result []byte

x:= big.NewInt(0).SetBytes(input)

base := big.NewInt(int64(len(b58Alphabet)))
zero := big.NewInt(0)

mod := &big.Int{}
for x.Cmp(zero) != 0 {
x.DivMod(x,base,mod)  // 對x取餘數
result =  append(result, b58Alphabet[mod.Int64()])
}



ReverseBytes(result)

for _,b:=range input{


if b ==0x00{
result =  append([]byte{b58Alphabet[0]},result...)
}else{
break
}
}


return result

}


//位元組陣列的反轉
func ReverseBytes(data []byte){
for i,j :=0,len(data) - 1;i<j;i,j = i+1,j - 1{
data[i],data[j] = data[j],data[i]
}
}
func generatePrivateKey(hexprivatekey string,compressed bool) []byte{
versionstr :=""
//判斷是否對應的是壓縮的公鑰,如果是,需要在後面加上0x01這個位元組。同時任何的私鑰,我們需要在前方0x80的位元組
if compressed{
versionstr  = "80" + hexprivatekey + "01"
}else{
versionstr  = "80" + hexprivatekey
}
//字串轉化為16進位制的位元組
privatekey,_:=hex.DecodeString(versionstr)
//通過 double hash 計算checksum.checksum他是兩次hash256以後的前4個位元組。
firsthash:=sha256.Sum256(privatekey)

secondhash:= sha256.Sum256(firsthash[:])

checksum := secondhash[:4]

//拼接
result := append(privatekey,checksum...)

//最後進行base58的編碼
base58result :=Base58Encode(result)
return base58result
}



func Base58Decode(input []byte) []byte{
result :=  big.NewInt(0)
zeroBytes :=0
for _,b :=range input{
if b=='1'{
zeroBytes++
}else{
break
}
}

payload:= input[zeroBytes:]

for _,b := range payload{
charIndex := bytes.IndexByte(b58Alphabet,b)  //反推出餘數

result.Mul(result,big.NewInt(58))   //之前的結果乘以58

result.Add(result,big.NewInt(int64(charIndex)))  //加上這個餘數

}

decoded :=result.Bytes()


decoded =  append(bytes.Repeat([]byte{0x00},zeroBytes),decoded...)
return decoded
}


//檢查checkWIF是否有效
func checkWIF(wifprivate string) bool{
rawdata := []byte(wifprivate)
//包含了80、私鑰、checksum
base58decodedata:= Base58Decode(rawdata)

fmt.Printf("base58decodedata:%x\n",base58decodedata)
length :=len(base58decodedata)


if(length <37){
fmt.Printf("長度小於37,一定有問題")
return false
}


private := base58decodedata[:(length-4)]
//得到檢查碼
//fmt.Printf("private:%x\n",private)
firstsha :=  sha256.Sum256(private)

secondsha := sha256.Sum256(firstsha[:])

checksum := secondsha[:4]
//fmt.Printf("%x\n",checksum)
//得到原始的檢查碼
orignchecksum:= base58decodedata[(length-4):]
// fmt.Printf("%x\n",orignchecksum)

//[]byte對比
if bytes.Compare(checksum,orignchecksum)==0{
return true
}

return false

}

//通過wif格式的私鑰,得到原始的私鑰。
func getPrivateKeyfromWIF( wifprivate string) []byte{
if checkWIF(wifprivate){
rawdata := []byte(wifprivate)
//包含了80、私鑰、checksum
base58decodedata:= Base58Decode(rawdata)
//私鑰一共32個位元組,排除了0x80
return base58decodedata[1:33]
}
return []byte{}

}


func main(){
//得到wif格式的私鑰
wifprivatekey:=generatePrivateKey("18d3e15d48b2df76562fab783eac137aaeb611e6ff0a193e12ceef1354220ac7",false)
fmt.Printf("%s\n",wifprivatekey)

//【】byte轉換為string
str := fmt.Sprintf("%s",wifprivatekey)

//得到原始的私鑰
privatekey :=getPrivateKeyfromWIF(str)
fmt.Printf("%x", privatekey)
}

參考資料

https://en.bitcoin.it/wiki/Private_key
https://en.bitcoin.it/wiki/Wallet_import_format
http://gobittest.appspot.com/PrivateKey

image.png