实现地址 / go实现简易区块链 #6

Words
332
Reading
2 min
Listen
Play
4y

比特币钱包中并不像普通帐户那样真的有钱,而是公私钥的集合。先来定义钱包(wallet)的结构:

type Wallet struct {
    PrivateKey ecdsa.PrivateKey
    PublicKey  []byte
}
type Wallets struct {
    Wallets map[string]*Wallet
}
func NewWallet() *Wallet {
    private, public := newKeyPair()
    wallet := Wallet{private, public}
    return &wallet
}
func newKeyPair() (ecdsa.PrivateKey, []byte) {
    curve := elliptic.P256()
    private, err := ecdsa.GenerateKey(curve, rand.Reader)
    pubKey := append(private.PublicKey.X.Bytes(), private.PublicKey.Y.Bytes()...)
    return *private, pubKey
}

可见钱包中除了密钥对,其它什么也没有。现在需要Wallets类型来维护这起集合。

//运算地址
func (w Wallet) GetAddress() []byte {
    pubKeyHash := HashPubKey(w.PublicKey)
    versionedPayload := append([]byte{version}, pubKeyHash...)
    checksum := checksum(versionedPayload)
    fullPayload := append(versionedPayload, checksum...)
    address := Base58Encode(fullPayload)
    return address
}

func HashPubKey(pubKey []byte) []byte {
    publicSHA256 := sha256.Sum256(pubKey)
    RIPEMD160Hasher := ripemd160.New()
    _, err := RIPEMD160Hasher.Write(publicSHA256[:])
    publicRIPEMD160 := RIPEMD160Hasher.Sum(nil)
    return publicRIPEMD160
}
func checksum(payload []byte) []byte {
    firstSHA := sha256.Sum256(payload)
    secondSHA := sha256.Sum256(firstSHA[:])
    return secondSHA[:addressChecksumLen]
}

GetAddress()把公钥进行一系列转换,得到地址,如果公开,别人就可以向它转帐了。转换的地址步骤如下:

  1. 获取公钥,使用RIPEMD160(SHA256(PubKey))执行两次hash算法。
  2. 给hash加上地址生成算法版本
  3. 使用SHA256(SHA256(payload))hash计算第2步的结果,得到的hash值前4bytes就是校验码。
  4. 把校验码附加到version+PubKeyHash组合。
  5. 使用Base58编码version+PubKeyHash+checksum组合

address.jpg

最后,算出了一个真正的比特币地址。如果你在不连网的情况下在本地运算,得到的公私钥对就是常说的冷钱包。它具有最高的安全性。如果你把私钥放到了服务器上以进行一些自动转账的功能,比如交易所,这就是热钱包。如果服务器被黑客成功攻击,私钥被泄露,比特币就成别人的了!所以,才有很多人说,私钥即一切!