幹什麼不好,非要做程式設計師,真是敗家。
阿新 • • 發佈:2018-12-21
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()) } }