释放双眼,带上耳机,听听看~!
比特币地址结构: 【版本 + 公钥哈希 + 验证码】
版本:默认0x00, 即可空白的一字节。
公钥:由非对称加密算法得出。
公钥哈希:就是给公钥做哈希算法得出的结果。
验证码:给 [版本 + 公钥哈希],sha256两次,取头4个字符作为验证码。
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 1package main
2
3import (
4 "bytes"
5 "crypto/ecdsa"
6 "crypto/elliptic"
7 "crypto/rand"
8 "crypto/sha256"
9 "log"
10 "fmt"
11
12 "golang.org/x/crypto/ripemd160"
13 "github.com/btcsuite/btcutil/base58"
14)
15
16const walletVersion = byte(0x00) // 钱包版本
17const addressChecksumLen = 4 // 验证码长度
18
19// 钱包
20type Wallet struct {
21 PrivateKey ecdsa.PrivateKey
22 PublicKey []byte
23}
24
25// 初始化钱包
26func NewWallet() *Wallet {
27 private, public := newKeyPair()
28 wallet := Wallet{private, public}
29
30 return &wallet
31}
32
33// 得到比特币地址
34func (w Wallet) GetAddress() string {
35 pubKeyHash := HashPubKey(w.PublicKey)
36
37
38 walletVersionedPayload := append([]byte{walletVersion}, pubKeyHash...)
39 checksum := checksum(walletVersionedPayload)
40
41 fullPayload := append(walletVersionedPayload, checksum...)
42 address := base58.Encode(fullPayload)
43
44 // 比特币地址格式:【钱包版本 + 公钥哈希 + 验证码】
45 return address
46}
47
48// 得到公钥哈希
49func HashPubKey(pubKey []byte) []byte {
50 publicSHA256 := sha256.Sum256(pubKey)
51
52 RIPEMD160Hasher := ripemd160.New()
53 _, err := RIPEMD160Hasher.Write(publicSHA256[:])
54 if err != nil {
55 log.Panic(err)
56 }
57 publicRIPEMD160 := RIPEMD160Hasher.Sum(nil)
58
59 return publicRIPEMD160
60}
61
62// 通过【钱包版本+公钥哈希】生成验证码
63func checksum(payload []byte) []byte {
64 firstSHA := sha256.Sum256(payload)
65 secondSHA := sha256.Sum256(firstSHA[:])
66
67 return secondSHA[:addressChecksumLen]
68}
69
70// 创建新的私钥、公钥
71func newKeyPair() (ecdsa.PrivateKey, []byte) {
72 curve := elliptic.P256()
73 private, err := ecdsa.GenerateKey(curve, rand.Reader)
74 if err != nil {
75 log.Panic(err)
76 }
77 pubKey := append(private.PublicKey.X.Bytes(), private.PublicKey.Y.Bytes()...)
78
79 return *private, pubKey
80}
81
82// 验证比特币地址
83func ValidateAddress(address string) bool {
84 pubKeyHash := base58.Decode(address)
85 actualChecksum := pubKeyHash[len(pubKeyHash)-addressChecksumLen:]
86 version := pubKeyHash[0]
87 pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-addressChecksumLen]
88 targetChecksum := checksum(append([]byte{version}, pubKeyHash...))
89
90 return bytes.Compare(actualChecksum, targetChecksum) == 0
91}
92
93
94func main() {
95 for i:=0; i<100;i++ {
96 w := NewWallet()
97 fmt.Println(w.GetAddress())
98 }
99}
100
101