科普| 私鑰是什麼
免責聲明:本文涉及的所有私鑰都僅用於教育目的。請勿使用本文分享的任何代碼、密鑰或地址來保存任何種類、任何數量的密碼學貨幣資產。
以私鑰為原材料
正如我在本系列第一篇文章《私鑰是什麼》中所述,生成私鑰的過程依賴於偽隨機數生成器(PRNG)和足夠大的熵。關於私鑰,最重要的一點是,它是從1 到2²⁵⁶-1 的範圍內隨機選出的整數。只要是在這個範圍內的數,都可以用作私鑰。
既然我們已經初步學習了私鑰背後的數學知識,接下來就可以自己生成有效的私鑰了(譯者註:教育目的,可跟隨作者的思路學習,但不推薦自己生成。)。我們不妨將私鑰生成過程想像成一個長達78 位的水平數字組合鎖(其可能組合數量恰好等於2²⁵⁶-1),然後我們把這個密碼鎖分成3 排,每排有26 位。你可以把PRNG 函數想像成一個會隨機打亂數字,打亂出一個數字組合的東西:一開始每一位都是0,然後毫無章法地在每一位上選出一個具體的數字。假設我們使用PRNG 函數生成亂序的數字組合,得到以下三排數字:
(1) 04406941321102621719184878;
(2) 43014596507006094171646853;
(3) 06780198554267270848908554;
- 瀏覽器使用Web Cryptography API (提供Crypto.getRandomValues(32) 之類的密碼學原語,或者等價的32 字節緩衝區)作為PRNG。這個PRNG 使用你的計算機熵源作為隨機種子來生成隨機數。在生成隨機數的時候,請一定要使用電子熵源,因為一些研究表明,人類比較不擅長選擇隨機數字(人自己選出來的數字是有模式的,到不到偽隨機的要求) -
恭喜!你現在已經是私鑰 44069413211026217191848784301459650700609417164685306780198554267270848908554 的所有者了。
我們可以使用這個私鑰生成一個比特幣或以太坊地址,或者任何以1 至2²⁵⁶-1 為私鑰範圍的區塊鏈的地址。
要根據這個私鑰生成一個以太坊地址,我們需要使用橢圓曲線點乘算法(需要一篇專門的文章才能講清楚)。因此,簡單起見,我們會把它交給計算機處理。為此,我們需要把這個私鑰“告訴”計算機。麻煩的是,計算機不會處理十進制形式的信息,它只能理解二進制代碼。目前,我們的只有十進制數形式的私鑰。因此,我們先要將這個私鑰從十進制數形式轉換為計算機可以理解的比特(bit,也譯成“位” 或“位元”)和字節(byte,一個字節等於8 個比特)。
位和字節
在進行下一步操作之前,我們需要先了解什麼是比特和字節。任何數字設備都只能理解由0 和1 組成的信息,通常被稱為比特。比特就是“二進制數字”,即,僅使用1 和0 表示的數字。雖然我們的智能手機和電腦都可以顯示漢字和圖片,還能播放歌曲,它們最終都是比特來表示並處理這些信息的。位越多,表示的信息越大,但說到底無非是一堆0 和1 而已。
根據上下文,多個位可以表示字符(如,在使用ASCII 編碼時,字母a 的定義就是01100001)或數字(01100001 也可以用來表示十進制數97)。在將十進制整數轉換為二進制形式時,就是將其轉換成以2 為底數的冪之和,其中每個冪的指數遞增。例如,我們通常採用十進制形式記數,十進制數就是以10 為底數的冪之和。因此,在使用二進制時,在2 的 N 次冪以內的整數,我們就可以用n 個位來表示和存儲。
- 8 位電子遊戲機最高能夠表達的十進制數是255,因為它們使用的中央處理單元(CPU)最多只能執行8 位操作(譯者註:上圖的左邊解釋了為什麼N 個位就可以表示2 的N 次冪以內的數-- 因為其數字組合有2 的N 次冪種可能性;右邊則演示了一個二進制數意味著多大的整數,即相互轉換的計算規則-
雖然我們可以使用二進制形式來表達任何數字,但是二進制形式過於“繁冗”。如果要表示97,我們需要8 個二進制數字。二進制數對於計算機來說很容易處理,但是不方便人類閱讀。因此,計算機通常會使用十六進製而非二進制來表示數據:位置數字系統以16 為底數來表示數字。一位十六進制數可表示四位二進制數。我們可以用十六進制數61 來表示二進制數01100001 或十進制數97,這樣就比二進制少了6 位數。十六進制數使用ABCDEF 來表示10 至15,通常用來縮小數據。
私鑰有多少個比特?
再說回私鑰,我們知道私鑰的範圍是1 至2²⁵⁶-1。我們該如何用位來表示它?需要用到多少位?如上文所述,在將十進制整數轉換為二進制形式時,就是將其轉換成以2 為底數的冪之和。在使用8 位二進制數時,我們能表示的最大的數是2⁷ + 2⁶ + 2⁵ + 2⁴ + 2³ + 2² + 2¹ + 2⁰,即,整數255。我們可以看出,要表達2^n 以內的數,我們就需要n 個位。由此可推得,我們需要256 位,或者說32 字節(256/8),來表示我們的私鑰。
- 十六進制數據表示旨在減少表示數字所需的位數。但是,計算機依然只能使用二進制來處理數據-
如果我們一致同意需要使用32 字節來表示我們在[1, 2²⁵⁶-1] 範圍內的私鑰,那麼在十六進制形式下,我們需要64 個數來表示私鑰。現在,我們可以將原始私鑰
44069413211026217191848784301459650700609417164685306780198554267270848908554
轉換成十六進制形式:
616E6769652E6A6A706572657A616775696E6167612E6574682E6C696E6B0D0A看到十六進制私鑰中多出的字母A、B、C、D、E 了嗎?看到這些字母,我們就可以輕易辨別出這個數是十六進制的。
從私鑰到公鑰
現在,我們可以把這個十六進制私鑰告訴我們的計算機了。我們可以使用JavaScript 之類的編程語言輕鬆導入這個十六進制私鑰,以便用於之後的乘法運算。在以下代碼中,之前得到的十六進制數被導入作為私鑰(“sk”是secret_key 的縮寫,是密碼學中的標準記法)。這個十六進制數是以16 為底數的。
- 通過使用BigNumber 庫,我們可以確保轉換過程中不會丟失任何小數。這些數字通常會被表達成指數(例如,4.406941321102622e+76),而且如果我們直接將其解析成十六進制,就會失去精度。如果不使用BigNumber 庫,我們得到的十六進制私鑰就會變成616e6769652e6c00000000000000000000000000000000000000000000000000 -
導入私鑰之後,下一步就是創建公鑰。你可能還記得,我們在第一篇文章中提到過,在獲取以太坊地址之前,我們先要通過私鑰來生成公鑰。根據以太坊黃皮書所述,公鑰生成過程遵循的是標準的ECDSA 公鑰生成算法,其中,我們將私鑰乘以生成器點得到一個坐標,將該坐標的x 值和y 值前後拼在一起就是公鑰。我們的公鑰(在密碼學中記為“pk”)可以用來生成我們的以太坊地址。
- x 和y 是使用橢圓曲線上的點乘以我們的私鑰(sk)得到的。雖然私鑰可以在任意區塊鏈中作為一個地址的唯一生成器,以太坊專門使用橢圓曲線secp256k1 生成公鑰;因此,私鑰的簽名操作也跟這條曲線有關-
終於到了最後一步。有了公鑰,我們就執行黃皮書中的最後一個操作:
給定某個私鑰,以太坊地址A 是對應ECDSA 公鑰的Keccak 哈希值的最右邊160 位。
鑑於我們已經有了自己的ECDSA 公鑰,剩下的唯一一件事是在我們的公鑰上執行Keccak 哈希函數,取結果最右邊的160 位。當我們將這些操作結果存儲在“緩衝區”(就好像存儲信息的小盒子)時,我們可以“丟掉”(切片)前24 個十六進制數,只留下後40 個十六進制數,或者更準確地說,20 個字節(這就是以太坊地址的長度)。
- 以太坊地址被設計為20 個字節。有人認為刪掉一些字節(具體來說是12 個字節)可能會引起碰撞,導致兩個私鑰生成相同的以太坊地址。不過到目前為止,還沒發生過這種情況-
你的個人專屬錢包
如你所見,只要一個數(雖然很長)就可以生成一個以太坊地址來存儲各類資產:從代表虛擬貓、磁帶、襪子和門票等物品的NFT 到具有增值潛力的密碼學資產等等。你的以太坊地址是公開的,而且像你的家庭住址一樣,但是只能通過鑰匙打開。如果你不想自己來處理所有這些流程,你可以在Portis 上註冊一個賬戶。 Portis 會自動為你創建私鑰(這個私鑰只有你知道,因為它採用的是端到端加密架構)以及對應的以太坊地址,供你在100 多個dApp 中使用。
在本系列下一篇(也是最後一篇)文章中,我們將介紹如何使用私鑰來創建並廣播交易、簽署消息,以及這些簽名在以太坊生態中有什麼影響。
(完)
(文內有許多超鏈接,可點擊左下”閱讀原文“ 從EthFans 網站上獲取)
原文鏈接:
https://medium.com/portis/part-two-turning-random-numbers-into-an-ethereum-address-3928f56b225c
作者: Jose Aguinaga