-
Notifications
You must be signed in to change notification settings - Fork 18
/
wallet.go
124 lines (100 loc) · 2.89 KB
/
wallet.go
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
package main
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"fmt"
"github.com/btcsuite/btcutil/base58"
"golang.org/x/crypto/ripemd160"
)
// - 结构定义
type wallet struct {
//私钥
PriKey *ecdsa.PrivateKey
//公钥原型定义
// type PublicKey struct {
// elliptic.Curve
// X, Y *big.Int
// }
// 公钥, X,Y类型一致,长度一致,我们将X和Y拼接成字节流,赋值给pubKey字段,用于传输
// 验证时,将X,Y截取出来(类似r,s),再创建一条曲线,就可以还原公钥,进一步进行校验
PubKey []byte
}
// - ==创建秘钥对==
func newWalletKeyPair() *wallet {
curve := elliptic.P256()
//创建私钥
priKey, err := ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
fmt.Println("ecdsa.GenerateKey err:", err)
return nil
}
//获取公钥
pubKeyRaw := priKey.PublicKey
//将公钥X,Y拼接到一起
pubKey := append(pubKeyRaw.X.Bytes(), pubKeyRaw.Y.Bytes()...)
//创建wallet结构返回
wallet := wallet{priKey, pubKey}
return &wallet
}
// - ==根据私钥生成地址==
func (w *wallet) getAddress() string {
//公钥
// pubKey := w.PubKey
pubKeyHash := getPubKeyHashFromPubKey(w.PubKey)
//拼接version和公钥哈希,得到21字节的数据
payload := append([]byte{byte(0x00)}, pubKeyHash...)
//生成4字节的校验码
checksum := checkSum(payload)
//25字节数据
payload = append(payload, checksum...)
address := base58.Encode(payload)
return address
}
//给定公钥,得到公钥哈希值
func getPubKeyHashFromPubKey(pubKey []byte) []byte {
hash1 := sha256.Sum256(pubKey)
//hash160处理
hasher := ripemd160.New()
hasher.Write(hash1[:])
// 公钥哈希,锁定output时就是使用这值
pubKeyHash := hasher.Sum(nil)
return pubKeyHash
}
//通过地址,反推出公钥哈希,注意不是公钥
func getPubKeyHashFromAddress(address string) []byte {
//base58解码
decodeInfo := base58.Decode(address)
if len(decodeInfo) != 25 {
fmt.Println("getPubKeyHashFromAddress, 传入地址无效")
return nil
}
//需要校验一下地址
//截取
pubKeyHash := decodeInfo[1 : len(decodeInfo)-4]
return pubKeyHash
}
//得到4字节的校验码
func checkSum(payload []byte) []byte {
first := sha256.Sum256(payload)
second := sha256.Sum256(first[:])
//4字节checksum
checksum := second[0:4]
return checksum
}
func isValidAddress(address string) bool {
// 解码,得到25字节数据
decodeInfo := base58.Decode(address)
if len(decodeInfo) != 25 {
fmt.Println("isValidAddress, 传入地址长度无效")
return false
}
// 截取前21字节payload,截取后四字节checksum1
payload := decodeInfo[:len(decodeInfo)-4] //21字节
checksum1 := decodeInfo[len(decodeInfo)-4:] //4字节
// 对palyload计算,得到checksum2,与checksum1对比,true校验成功,反之失败
checksum2 := checkSum(payload)
return bytes.Equal(checksum1, checksum2)
}