最近研究了研究比特币,水一篇

废话少说,先上代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
    "crypto/sha256"
    "fmt"

    base58 "github.com/jbenet/go-base58"
)

func main() {
    //以任意字符串作为种子生成私钥
    seed := []byte("halu.lu")
    privateKey := sha256.Sum256(seed)
    fmt.Printf("Your hex private key is : %x\n", privateKey)
    wifKeyBytes := append([]byte{0x80}, privateKey[:]...)
    hash1 := sha256.Sum256(wifKeyBytes)
    hash2 := sha256.Sum256(hash1[:])
    wifKeyBytes = append(wifKeyBytes, hash2[:4]...)
    wifKey := base58.Encode(wifKeyBytes)
    fmt.Printf("Your wif private key is : %s\n", wifKey)
}

比特币私钥是由一个ECDSA私钥生成的,而ECDSA私钥可以是0到FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F之间的任何一个整数,前面那玩意是:
$$2^{256}-2^{32}-2^{9}-2^{8}-2^{7}-2^{6}-2^{4}-2^{0}$$ 这玩意略小于2^256。所以我们通常用SHA256生成一个值,再检验这个值是否满足要求(不符合的概率极小,我懒得检验了),这样我们就可以得到ECDSA的私钥。

但我们一般不直接用ECDSA私钥做比特币私钥,通常在钱包里导入导出的格式是WIF(Wallet Import Format),这种格式导出后是Base58字符串,以5开头,而压缩格式WIF私钥以K或L开头。

格式 私钥
16进制ECDSA 90b57c1a64fbc39b2e516fcc4f69fa55307d3ddb53da90a66f4da46c6a0f4102
WIF 5Jv1yc8RLkYhgAn7DveWe9Xm14R9taNbq8A6AkdHY772bc5APZJ

下面说一下怎么从16进制的ECDSA私钥生成WIF格式的私钥

  1. 首先我们有一个ECDSA私钥(大小为32bytes,通常用SHA-256生成)

    90b57c1a64fbc39b2e516fcc4f69fa55307d3ddb53da90a66f4da46c6a0f4102 ①

  2. 向①头部加入一个值为0x80的字节

    8090b57c1a64fbc39b2e516fcc4f69fa55307d3ddb53da90a66f4da46c6a0f4102 ②

  3. 计算②的SHA256哈希值

    53aef433b9bc580580caa7fb578b0c75ce40e3460c60baba11e3cbf3e4f98ae4③

  4. 计算③的SHA256哈希值

    c8ce99f17c9064c7517938b685d553f26609a6a180f93b91ab5581b9f459b426 ④

  5. 向1的尾部加入④的前4个字节

    8090b57c1a64fbc39b2e516fcc4f69fa55307d3ddb53da90a66f4da46c6a0f4102c8ce99f1 ⑤

  6. 计算⑤的BASE58值,得到WIF格式的私钥 5Jv1yc8RLkYhgAn7DveWe9Xm14R9taNbq8A6AkdHY772bc5APZJ

嗯,就这么简单,但我当初折腾了好几天…

最后是我的比特币地址 12y5Ph8p4FYfpRzRyAi2MLh2irafY8gwHE 你们看着办吧(手动滑稽)

参考