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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章