比特幣賬戶私鑰、公鑰、地址的生成


由上一篇ECC算法筆記記錄的公鑰生成方式:K = k * G :

私鑰 k 通常是隨機選出的一串數字串(經過sha256加密),然后通過ECC算法來產生一個公鑰(K),最后通過單項Hash算法來生成Bitcoin地址。

描述:

  • 地址是為了人們交換方便而弄出來的一個方案,因為公鑰太長了(130字符串或66字符串)。地址長度為25字節,轉為base58編碼后,為34或35個字符。base58是類似base64的編碼,但去掉了易引起視覺混淆的字符,又在地址末尾添加了4個字節校驗位,保障在人們交換個別字符錯誤時,也能夠因地址校驗失敗而制止了誤操作。
  • 由於存在公鑰有兩種形式,那么一個公鑰便對應兩個地址。這兩個地址都可由同一私鑰簽署交易。

密鑰類型

存在三種密鑰,並且都是使用 Base58Check 編碼成 ASCII 碼呈現:

  • 私鑰 (private key)
  • 公鑰 (public key)
  • 地址 (address)

比特幣地址生成的過程

 

第一步:私鑰 (private key)產生

  偽隨機數產生的256bit私鑰示例:

  8F72F6B29E6E225A36B68DFE333C7CE5E55D83249D3D2CD6332671FA445C4DD3

第二步:公鑰 (public key)

  1. 拿私鑰產生256bit私鑰經secp256k1橢圓曲線推出的公鑰(前綴04+X公鑰+Y公鑰):

  04

  06CCAE7536386DA2C5ADD428B099C7658814CA837F94FADE365D0EC6B1519385

  FF83EC5F2C0C8F016A32134589F7B9E97ACBFEFD2EF12A91FA622B38A1449EEB  

       2. 計算公鑰的 SHA-256 哈希值(32bytes):

  2572e5f4a8e77ddf5bb35b9e61c61f66455a4a24bcfd6cb190a8e8ff48fc097d

       3. 取上一步結果,計算 RIPEMD-160 哈希值(20bytes):

  0b14f003d63ab31aef5fedde2b504699547dd1f6

       4. 取上一步結果,前面加入地址版本號(比特幣主網版本號“0x00”):

  000b14f003d63ab31aef5fedde2b504699547dd1f6

  5. 取上一步結果,計算兩次 SHA-256 哈希值(32bytes)

  ---1--- ddc2270f93cc84cc6869dd373f3c340bbf5cb9a8f5559297cc9e5d947aab2536

  ---2--- 869ac57b83ccf75ca9da8895823562fffb611e3c297d9c2d4612aeeb32850078

  6. 取上一步結果的前4個字節(8位十六進制)

  869ac57b  

  7. hash of public key,把這4個字節加在第4步的結果后面,作為校驗(這就是比特幣地址的16進制形態)

  000b14f003d63ab31aef5fedde2b504699547dd1f6869ac57b  

第三步:地址 (address)

  最終給用戶使用的:用base58編碼變換一下地址(這就是最常見的比特幣地址形態)

  121bWssvSgsA9SKjR4DbYncEAoJjmBFwog

 

如何生成私鑰(private key)

本質上私鑰就是一串隨機選出的 256 個 bit 的 01 數字(32 字節 * 8 = 256 bits),但是這串數字卻控制着你的比特幣賬號的所有權,因此這串數字相當重要,要具有足夠的隨機性,一般采用密碼學安全的偽隨機數生成器(CSPNG),並且需要有一個來自具有足夠熵值的源的種子(seed)。

比特幣客戶端軟件使用 Secp256k1ECDSA 標准生成橢圓曲線,使用橢圓生成一個私鑰,然后再從私鑰中生成對應的公鑰。

如果自行選取簡單的123456密碼,最終生成的賬戶可是“公交車賬戶”了哈哈。

選擇 32 個字節的原因是因為 Bitcoin 使用的是 ECDSA 算法,並且使用的是 secp256k1 曲線。

 

如何生成公鑰(public key)

Bitcoin 的公鑰是通過 橢圓曲線密碼學算法(K = k * G)來生成,其中公式中的:

  • K:公鑰;
  • k:私鑰,為上一段生成的 32 字節的字節數組(16 進制串表示);
  • G:為一個生成點;

Bitcoin 使用了 secp256k1 標准定義的一種特殊的橢圓曲線和一系列的數學常量。

如上公式,以私鑰 k 為起點,與預定的生成點 G 相乘來生成公鑰 K,並且因為所有 Bitcoin 用戶的生成點 G 都是相同的(常量),所以由一個確定的私鑰 k 生成一個確定的公鑰 K,並且是單向的。

# 私鑰生成公鑰示例(非壓縮公鑰)
private key: de97fdbdb823a197603e1f2cb8b1bded3824147e88ebd47367ba82d4b5600d73
public key:  047c91259636a5a16538e0603636f06c532dd6f2bb42f8dd33fa0cdb39546cf449612f3eaf15db9443b7e0668ef22187de9059633eb23112643a38771c630db911

 

壓縮格式的公鑰 (compressed public keys)

簡單來說,對於壓縮公鑰生成地址時,則只取非壓縮公鑰的X部分即可。

從上面的輸出示例中可以看到 public key 一共有 130 個 16 進制的字符,共 520 個字節,其中的前綴為 04,這里的 04 表示該公鑰為 非壓縮格式,即完整存儲了 x 和 y 坐標(各 256 個 bits),但是從 secp256k1 的橢圓曲線方式可以看到,只要知道其中一個坐標值,另外一個坐標值都是可以通過解方程得出的,因為可以只存儲其中一個坐標,這樣就可以節約 256 個 bits,從而引入了 壓縮格式 的公鑰。

上面的 04 前綴表示 非壓縮格式,如果為壓縮格式,則前綴為 02 或 03,有兩個前綴主要是因為方程(y² = x³ + ax + b)的左側的 y 為平方根,可能為正或者為負。

如下為一個與上面示例對應的壓縮格式的公鑰值:

private key:            de97fdbdb823a197603e1f2cb8b1bded3824147e88ebd47367ba82d4b5600d73
public key compressed:  037c91259636a5a16538e0603636f06c532dd6f2bb42f8dd33fa0cdb39546cf449

 

如何生成地址(公鑰哈希 hash of public key)

Bitcoin 的地址由公鑰經過單向的加密哈希算法 SHA256 和 RIPEMD160 生成,公式如下:

A = RIPEMD160(SHA256(K))

其中:
K 為公鑰
A 為最終生成的地址;

# 生成的地址示例,地址的長度為 40 個 16 進制串,即 160 個bits:
private key:            de97fdbdb823a197603e1f2cb8b1bded3824147e88ebd47367ba82d4b5600d73
public key compressed:  037c91259636a5a16538e0603636f06c532dd6f2bb42f8dd33fa0cdb39546cf449
address:                52dab5e951ef4848a31b7ead8437df8184acbc54

公鑰哈希就是大家看到的比特幣地址,大部分比特幣地址由公鑰通過 base58Check 編碼而來,把公鑰地址從 512-Bit 哈希到 160-Bit ,但並不是所有的比特幣地址都是公鑰推導出來,也有可能是通過腳本建立在比特幣網絡中的虛擬幣(比如彩色幣)的腳本標識。

 

Base58, Base58Check 以及壓縮格式

我們通常看到的 Bitcoin 地址都是經過 Base58Check 編碼后的地址,Base58Check 編碼也用於私鑰,加密的密鑰以及腳本中,用來提高可讀性和錄入的正確性。

下圖描述了通過 公鑰生成 Base58Check 編碼格式的地址的整個過程:

其中 Public Key Hash 我們在上面已經生成的地址,之后就是通過 Base58Check 編碼生成 Bitcoin 的地址格式。

(摘自 wiki)相比Base64,Base58不使用數字"0",字母大寫"O",字母大寫"I",和字母小寫"l",以及"+“和”/"符號。
設計Base58主要的目的是:

    • 避免混淆。在某些字體下,數字0和字母大寫O,以及字母大寫I和字母小寫l會非常相似。
    • 不使用"+“和”/"的原因是非字母或數字的字符串作為帳號較難被接受。
    • 沒有標點符號,通常不會被從中間分行。
    • 大部分的軟件支持雙擊選擇整個字符串。 

base58符號映射表

為了進一步增加安全性,Base58Check 格式又在 Base58 的基礎上新增了內置檢查錯誤的校驗和(checksum),該校驗和是添加到末尾的額外 4 個字節,校驗和的生成算法如下:

checksum = SHA256(SHA256(prefix+data))
  • data 為原始的數據;
  • prefix 前綴是個版本字段,是用來識別編碼的數據的類型,如:Bitcoin 地址(也是 public key hash)的前綴為 0(即 0x00),當前支持的如下類型:

 

其中 私鑰 的前綴為 128(即 0x80),對應的編碼后前綴為 5,如下為我們的私鑰編碼后的:

// base58編碼
de97fdbdb823a197603e1f2cb8b1bded3824147e88ebd47367ba82d4b5600d73
5KWKSRnmzxCjUP1NKR4dNyyHhaZWSGRTbGzBnm1vwgwpoe2AVGQ

 

下面為公鑰以及生成的 Base58Check 格式的地址信息:

// base58編碼
public key compressed:    037c91259636a5a16538e0603636f06c532dd6f2bb42f8dd33fa0cdb39546cf449
checksum: 4caf1695
base58check address:      18Z6R1VF7Do8RTHneeGzdVdbgjtXDVPmfS

 

base58check address:  18Z6R1VF7Do8RTHneeGzdVdbgjtXDVPmfS 
便於對應上面理解我們可以對比看看base58解碼后的BTC地址:
Version  Public key hash                           Checksum
00       62E907B15CBF27D5425399EBF6F0FB50EBB88F18  C29B7D93

 

 

Base58Check 的編碼過程:

因此實際上在 bitcoin 中大多數需要向用戶展示的數據都是使用的 Base58Check 編碼格式。

 

 

筆記總結參考:

學習 btc 錢包私鑰、公鑰和地址的生成過程

比特幣密鑰生成規則及 Go 實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM