EOS原始碼分析(4)錢包

尹成發表於2018-05-13
錢包是區塊鏈中一個很重要的概念。顧名思義,說到錢包的時候,我們一定會想到它是用來存錢的,但是數字化的錢包和現實社會的錢包還是有一些區別的。現實世界的錢包中真的放著法幣,而數字化錢包存放的是鑰匙,這把鑰匙可以開啟存放你餘額的保險箱。
我們拿支付寶錢包做一個例子,支付寶錢包這個應用中也沒有真實的錢,只有很多個賬號和密碼,每一對賬號和密碼都能開啟一個保險箱,這些保險箱統一寄存在阿里伺服器上。
區塊鏈錢包也和支付寶錢包類似,裡面沒有真實的貨幣,而是儲存了很多私鑰,每一把鑰匙都對應著一個數字貨幣的保險箱,這些保險箱則是儲存在區塊鏈上。這裡的金鑰就等同於支付寶中的一對賬號和密碼。這個私鑰有以下兩點作用:

1. 生成公鑰,從而生成交易地址(類似於你的支付二維碼)
2. 生成簽名,從而簽署一筆交易(類似於你的支付密碼)

有了以上這兩個功能後,你就可以與任何人進行貨幣的交易了。

EOS 錢包中也儲存著金鑰,但EOS錢包和其他區塊鏈錢包也存在著一些差異,主要差異在於EOS 中的金鑰主要是用來生成簽名的,它並不用來生成交易地址。也就是說上述私鑰中的兩點功能,EOS金鑰主要用來支援第二點功能。那如果缺少了第一點功能,別人如何向你轉賬呢? EOS 的解決辦法是引入了賬號的概念,賬號可以是2位到32位的任意字串,從而方便使用者記憶,使用者之間的轉賬是通過賬號來進行操作的。EOS團隊認為使用公鑰作為交易地址對使用者來說太不友好了,沒人能夠記得一長串無意義的字串,相比而言,人們更習慣以字串名稱作為賬號來使用,因此,EOS引入了賬號系統,每個賬號都對應的金鑰,主要用來進行簽名處理。

接下來,我們將具體瞭解下EOS系統中錢包所提供的主要介面及其具體的實現。
# 錢包工具
錢包的主要功能就是儲存私鑰,從而在生成交易的時候可以進行簽名。它一般是一個執行在你本地機器的程式。
在EOS系統中,錢包功能是以外掛的方式提供的,這使得它可以很容易的整合在EOS節點中執行,也可以作為一個獨立的程式執行;

- 整合在EOS節點中
在eosd 所引用的config.ini 檔案中加入錢包支援:`plugin = eosio::wallet_api_plugin`, 增加以上配置後,節點就支援錢包介面呼叫了
- 獨立的程式執行
錢包應用的路徑為:`path-to-eos/build/programs/eos-walletd`,直接執行此程式即可

## 錢包所支援的命令
`eos-walleted`是一個後臺程式,它不直接支援命令列引數,但它支援RPC呼叫,你可以通過`eosc` 程式與其進行互動,此程式的路徑為:`eos/build/programs/eosc`。其提供的命令如下:

### Create
```
$ eosc wallet create ${options}
```

Options:
-n, --name TEXT=default 錢包的名稱,預設名稱為default

### Open
開啟已建立的錢包。錢包只有處於開啟狀態,才能對其進行進一步的操作。
```
$ eosc wallet open ${options}
```
Options:
-n,--name TEXT 所要開啟錢包的名稱

### Lock
對錢包進行加鎖,一旦加鎖後,就不能再對錢包進行其他操作了,解鎖後才可進一步操作。

```
$ eosc wallet lock ${options}
```

Options:
-n,--name TEXT 需要加鎖的錢包名稱

### Unlock
對錢包進行解鎖。

```
$ eosc wallet unlock ${options}
```
Options:
-n,--name TEXT 需要解鎖的錢包名稱
--password TEXT 錢包密碼,這個密碼是在建立錢包時生成的

### Import private key into wallet
把私鑰匯入到錢包中,如果你想使用某一賬號進行轉賬等操作,則此賬號對應的私鑰必須匯入到錢包中才能進行。

```
$ eosc wallet import ${options} key
```
Positionals:
key TEXT 將要匯入的私鑰,格式為 WIF。

Options:
-n,--name TEXT 錢包名稱

### List
羅列出所有開啟的錢包, *號標示的錢包表示其狀態為 unlocked

```
$ eosc wallet list
```

### Keys
羅列出所有unlocked狀態錢包中的私鑰,格式為 WIF。

```
$ eosc wallet keys
```
# 錢包金鑰

在上一章中我們介紹了錢包中其實儲存的就是金鑰資訊,在本章中我們具體介紹這些金鑰是如何生成的。

### 私鑰
#### 私鑰的重要性
私鑰非常重要,可以說你賬戶的安全性就是通過私鑰保證的。如果其他人知道了你的私鑰資訊,則他可以對你的EOS 賬號進行任何操作。在大部分割槽塊鏈系統中,如果丟失了私鑰,就意味著丟失了私鑰所對應的賬戶餘額資訊,你是無法通過其他方式找回的,因此網上提供了很多熱備份,冷備份,硬體備份等私鑰備份方案。在EOS系統中,雖然存在著賬號恢復的手段,但私鑰洩密後,賬戶上的餘額也隨時可能會被轉走,因此,妥善保管私鑰是儲存區塊鏈數字資產的關鍵。

#### 私鑰的生成
那私鑰到底是什麼東西?其實它就是一個數字,是一個由256位的二進位制組成的數字。這個數字是隨機產生出來的,隨機產生的目的是為了避免出現重複。既然是256個二進位制資料,那產生方式就有很多了,如果你足夠有耐心,甚至可以通過拋擲256次硬幣的方式來產生,將硬幣的正反面轉換為0和1,由此得到一個256位的二進位制數字。其本質是在1~2^256之間選擇一個數字。計算機的實現一般是通過一個密碼學安全的隨機源中取出一長串隨機位元組,對其使用SHA256雜湊演算法進行運算,這樣就可以方便的產生一個256位的數字。
私鑰在EOS中的儲存是使用WIF(Wallet Import Format)格式的,這種格式廣泛的應用在錢包之間金鑰的輸入和輸出。WIF還有一個壓縮版本的格式,所謂的壓縮主要是用來區分其公鑰是否進行壓縮,在區塊鏈交易過程中,公鑰大量被使用,因此對其壓縮可以縮減交易的位元組數。
#### 私鑰不同格式的轉換
通過以上介紹,你已經瞭解了三種私鑰的形式,他們分別是256位二進位制格式,WIF未壓縮格式和WIF壓縮格式,他們之間如何相互轉換?

假設隨機生成的私鑰如下:

```
P = 0x9B257AD1E78C14794FBE9DC60B724B375FDE5D0FB2415538820D0D929C4AD436
```

新增字首0x80

```
WIF = Base58(0x80 + P + CHECK(0x80 + P) + 0x01)
= Base58(0x80 +
0x9B257AD1E78C14794FBE9DC60B724B375FDE5D0FB2415538820D0D929C4AD436 +
0x36dfd253 +
0x01)
```
其中CHECK表示兩次sha256雜湊後取前四個位元。字首0x80表示私鑰型別,字尾0x01表示公鑰採用壓縮格式,如果用非壓縮公鑰則不加這個字尾。WIF格式的私鑰的首字元是以“5”,“K”或“L”開頭的,其中以“5” 開頭的是WIF未壓縮格式,其他兩個是WIF壓縮格式。

#### 加密私鑰
正應為私鑰在區塊鏈中格外的重要,因此促進了加密私鑰標準BIP0038 的出臺,該標準能夠被眾多不同的錢包和比特幣客戶端理解,實現私鑰的加密。

BIP0038 加密方案是:輸入一個私鑰,使用WIF對私鑰進行編碼,此外,讓使用者再輸入一個長密碼作為口令,通常是由多個單詞或者一段複雜的數字字母字串組成。通過加密之後,最終得到的結果是一個加密私鑰,字首為6P。

因此,當你看到了一個以6P開頭的金鑰,說明該金鑰被加密過,需要一個口令來將其轉換為WIF格式的私鑰。

### 公鑰
公鑰的設計就是為了在網路中傳輸的,它可以保證使用者即便沒有私鑰,仍然可以通過公鑰證明交易就是公鑰所對應的賬號產生的。其重要的三個特性如下:

1. 公鑰是由私鑰計算出來的,使用公鑰加密的資料,私鑰可以解碼
2. 公鑰無法逆向計算出私鑰
3. 用私鑰計算的簽名,可以通過公鑰進行驗證

#### 公鑰的生成
在橢圓加密演算法(ECC)流行之前,絕大多數的公鑰加密演算法都是使用RSA,DSA這些基於模運算的替代加密系統,這些加密演算法在今天依然佔據非常重要的位置。但相比於這些演算法,橢圓加密演算法有其特殊的優勢:

1. 安全效能更高, 如160位ECC與1024位RSA,DSA有相同的安全強度
2. 計算量小,處理速度快,在私鑰的處理速度上(解密和簽名),ECC遠比RSA,DSA快得多
3. 儲存空間佔用小,ECC的金鑰尺寸和系統引數與RSA,DSA相比要小得多
4. 頻寬要求低使得ECC具有廣泛的應用前景

因此,區塊鏈的公鑰生成演算法一般都使用了橢圓加密演算法,EOS也不例外。

橢圓曲線的定義非常簡單,滿足下面公式的所有(x,y)座標的集合,就是我們所說的橢圓曲線:

`y² mod p = (x³ + 7) mod p`

上面的公式中,mod 是取餘符號,而 P 是一個很大的素數。因此公鑰的幾何意義,其實就是橢圓曲線上的一個點,由一對座標(x,y)組成。公鑰通常表示為字首04緊接著兩個256位元的數字。04是型別標記,表示無壓縮公鑰。之後的兩個256位分別對應著x和y座標,共計65位元組。

而公式中的P 取不同素數的時候,橢圓曲線會呈現出完全不同的形態,P越大,這個橢圓也就越大,可承載的數值範圍也就越大,衝突率會降低,乃至於更安全,所以出於安全性考慮,比特幣中採用的是一個特定的橢圓曲線,我們叫它spec256k1,它是由NIST(National Institute of Standards and Technology)這個組織確定的。spec256k1所選取的P有多大呢? 我們可以看一下:

```
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
```

根據P 的選取,橢圓曲線相當於被定義在一個素數階的有限域內,而不是定義在實數範圍,他的函式影象看起來像分散在兩個維度上的散點圖。針對曲線上的點,我們可以定義加法和乘法運算,而公鑰的產生正是使用了乘法運算,如下:

```
{K = priv * G}
```
其中priv是隨機生成的私鑰,G是橢圓曲線上的某一個點,而K 則是生成的公鑰。G這個點稱作生成點,它是spec256k1標準的一部分,可以認為是規定的一個固定的值。因此,根據私鑰priv就可以生成公鑰K,priv 和K 之間的關係是固定的,但只能單向運算,即從priv得到K。


#### 公鑰的格式
公鑰常見的有兩種格式,一種是未壓縮格式公鑰,另一種是壓縮格式公鑰。引入壓縮格式公鑰是為了減少區塊鏈交易的位元組數。其中,未壓縮格式公鑰使用04作為字首,之後是兩個256位元,分別對應橢圓曲線點的x和y座標,示例如下:

```
x = 97FCFAA24237514FD4C00A33491F835D7D019DE4E9CEB0E24916371BAE329E62
```

```
y = 2260575B83A1542D93418DABBBE65109B4E27A1A0737B2FD980698C3D0188839
```

則未壓縮的公鑰表示為:

```
K = 0x0497FCFAA24237514FD4C00A33491F835D7D019DE4E9CEB0E24916371BAE329E622260575B83A1542D93418DABBBE65109B4E27A1A0737B2FD980698C3D0188839
```

以上公鑰共需65個位元組來表示。

由於公鑰就表示橢圓曲線上的一個點,我們從橢圓曲線的公式可以看到,在已知x 的情況下,我們可以求算出y 的兩個解,在實數域它們顯然是一正一負兩個值;而在spec256k1橢圓曲線上則是一奇一偶兩個數。那麼只需記錄x座標和y的奇偶性(而不是y本身),這樣我們就能砍掉近一半的空間表示同樣的公鑰,如下:

```
K' = 0x0397FCFAA24237514FD4C00A33491F835D7D019DE4E9CEB0E24916371BAE329E62
```
這個K'被稱為壓縮公鑰,首位元組是0x02(對應偶數y)或0x03(對應奇數y),公計33位元組。

### EOS 公鑰






網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN




網址:http://www.qukuailianxueyuan.io/



欲領取造幣技術與全套虛擬機器資料

區塊鏈技術交流QQ群:756146052  備註:CSDN

尹成學院微信:備註:CSDN

相關文章