比特币地址结构: 【版本 + 公钥哈希 + 验证码】

版本:默认0x00, 即可空白的一字节。
公钥:由非对称加密算法得出。
公钥哈希:就是给公钥做哈希算法得出的结果。
验证码:给 [版本 + 公钥哈希],sha256两次,取头4个字符作为验证码。
package main import ( "bytes" "crypto/ecdsa" "crypto/elliptic" "crypto/rand"
"crypto/sha256" "log" "fmt" "golang.org/x/crypto/ripemd160"
"github.com/btcsuite/btcutil/base58" ) const walletVersion = byte(0x00) // 钱包版本
const addressChecksumLen = 4 // 验证码长度 // 钱包 type Wallet struct { PrivateKey
ecdsa.PrivateKey PublicKey []byte } // 初始化钱包 func NewWallet() *Wallet {
private, public := newKeyPair() wallet := Wallet{private, public} return
&wallet } // 得到比特币地址 func (w Wallet) GetAddress() string { pubKeyHash :=
HashPubKey(w.PublicKey) walletVersionedPayload := append([]byte{walletVersion},
pubKeyHash...) checksum := checksum(walletVersionedPayload) fullPayload :=
append(walletVersionedPayload, checksum...) address :=
base58.Encode(fullPayload) // 比特币地址格式:【钱包版本 + 公钥哈希 + 验证码】 return address } //
得到公钥哈希 func HashPubKey(pubKey []byte) []byte { publicSHA256 :=
sha256.Sum256(pubKey) RIPEMD160Hasher := ripemd160.New() _, err :=
RIPEMD160Hasher.Write(publicSHA256[:]) if err != nil { log.Panic(err) }
publicRIPEMD160 := RIPEMD160Hasher.Sum(nil) return publicRIPEMD160 } //
通过【钱包版本+公钥哈希】生成验证码 func checksum(payload []byte) []byte { firstSHA :=
sha256.Sum256(payload) secondSHA := sha256.Sum256(firstSHA[:]) return
secondSHA[:addressChecksumLen] } // 创建新的私钥、公钥 func newKeyPair()
(ecdsa.PrivateKey, []byte) { curve := elliptic.P256() private, err :=
ecdsa.GenerateKey(curve, rand.Reader) if err != nil { log.Panic(err) } pubKey
:= append(private.PublicKey.X.Bytes(), private.PublicKey.Y.Bytes()...) return
*private, pubKey } // 验证比特币地址 func ValidateAddress(address string) bool {
pubKeyHash := base58.Decode(address) actualChecksum :=
pubKeyHash[len(pubKeyHash)-addressChecksumLen:] version := pubKeyHash[0]
pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-addressChecksumLen] targetChecksum
:= checksum(append([]byte{version}, pubKeyHash...)) return
bytes.Compare(actualChecksum, targetChecksum) == 0 } func main() { for i:=0;
i<100;i++ { w := NewWallet() fmt.Println(w.GetAddress()) } }