既然我們已經可以產生橢圓曲線金鑰對,我們接下來就用使用它來進行訊息的簽名和驗證。我所指的訊息是任何形式,無論是文字還是二進位制形式,只要它們有被驗證合法性的需要。特別的是,bitcoin客戶端通過簽名來證明交易的有效性,反之,礦工則是通過驗證這樣的簽名,來批准並廣播合法的交易。
橢圓曲線簽名演算法就是ecdsa(elliptic-curve digital signature algorithm).在ecdsa中,各方必須約定乙個共同的雜湊函式h
, 因為我們將要簽名的物件是h(訊息)
下面的案例中,我們簽名的物件是sha-256
摘要。但bitcoin中指定的h
函式是hash256
,也就是指雙重sha-256
。
簽名第一步把我們的訊息存入檔案,命名ex-message.txt
。
this is a very confidential message
之後,我們用私鑰對其sha-256
摘要進行簽名。
$ openssl dgst -sha256 -sign ec-priv.pem ex-message.txt >ex-signature.der
ex-signature.der
檔案是簽名的der
格式。openssl使用der
編碼任何二進位制輸出,但這裡我們忽略這個細節。你不需要了解ecdsa簽名的語法,只需要記住它僅僅是一組的大數對(r,s)。
你可能會注意到,每一次你執行程式,簽名都發生變化,也就是說預設的簽名過程是不具有確定性的。這就給序列化區塊鏈交易時帶來了問題,因為簽名是交易
位元組序列中的一部分,並且你一定知道txid
是對交易
進行雜湊得來的。因此,每當你簽名一筆交易
,txid
就會隨之變化。這種行為也是造成交易可塑性
的原因之一。
為了顯示十六進製制編碼的簽名,只需新增-hex
引數。
$ openssl dgst -sha256 -hex -sign ec-priv.pem ex-message.txt
為了重用剛剛輸出的結果,最好使用hexdup
已生成的der
檔案。
$ hexdump ex-signature.der
驗證
無論什麼時候將合法訊息發布到網路,接收者都希望能夠得到乙個附件的簽名。在假設我們已經得到作者公鑰
的情況下,無論是原訊息
還是簽名
,都必須作為驗證流程的輸入資料:
$ openssl dgst -sha256 -verify ec-pub.pem -signature ex-signature.der ex-message.txt
我們使用**來完成上文中在命令列中完成的同樣的工作。
簽名openssl使簽名流程變得簡單,這一部分可以在ex-ecdsa-sign.c
中檢視。
uint8_t priv_bytes[32] = ;
const char message = "this is a very confidential message\n";
ec_key *key;
uint8_t digest[32];
ecdsa_sig *signature;
uint8_t *der, *der_copy;
size_t der_len;
...key = bbp_ec_new_keypair(priv_bytes);
bbp_sha256(digest, (uint8_t *)message, strlen(message));
signature = ecdsa_do_sign(digest, sizeof(digest), key);
ecdsa_sig
是乙個簡單的結構,用於儲存上文所說的(r,s)對:
struct ecdsa_sig;
使用i2d_ecdsa_sig
函式,我們也可以得到der
編碼的簽名:
der_len = ecdsa_size(key);
der = calloc(der_len, sizeof(uint8_t));
der_copy = der;
i2d_ecdsa_sig(signature, &der_copy);
驗證
驗證同樣很簡單,可以在ex-ecdsa-verify.c
中檢視:
uint8_t pub_bytes[33] = ;
uint8_t der_bytes = ;
const char message = "this is a very confidential message\n";
ec_key *key;
const uint8_t *der_bytes_copy;
ecdsa_sig *signature;
uint8_t digest[32];
int verified;
...key = bbp_ec_new_pubkey(pub_bytes);
der_bytes_copy = der_bytes;
signature = d2i_ecdsa_sig(null, &der_bytes_copy, sizeof(der_bytes));
因為無法得到私鑰,我們利用使用下面的輔助函式將pub_bytes
解碼為壓縮形式。
ec_key *bbp_ec_new_pubkey(const uint8_t *pub_bytes, size_t pub_len);
另一方面,der_bytes
是簽名程式返回的der
格式的簽名。我們將解碼der
簽名到更方便的ecdsa_sig
結構中,然後與訊息摘要比較進行驗證。
ecdsa_do_verify
函式的返回值:
注意:使用ecdsa_verify
可以跳過簽名的解碼過程,因為它需要的輸入值是der
形式的簽名。
深入區塊鏈以太坊原始碼之橢圓曲線演算法
橢圓曲線加密演算法elliptic curve cryptosystem 安全性基礎 橢圓曲線群上的離散對數問題。目前,最好解決演算法仍是指數時間。一 橢圓曲線群是由兩部分組成 第一部分是m。區域f中有兩個數a,b m y 2 x 3 ax b 其中x,y屬於f f 第二部分為o點 無窮遠點 橢圓曲...
密碼學中的橢圓曲線
密碼學中的橢圓曲線 密碼學中的橢圓曲線不是定義在是實數域上的,我們要把橢圓曲線定義在有限域上 顧名思義,有限域是一種只有由有限個元素組成的域 域的概念是從我們的有理數,實數的運算中抽象出來的,嚴格的定義請參考近世代數方面的數。簡單的說,域中的元素同有理數一樣,有自己得加法 乘法 除法 單位元 1 零...
區塊鏈中的隨機數演算法
randao是一種非常簡單的隨機性方法,因此非常常用。一般的想法是,網路的參與者首先都是私下選擇乙個偽隨機數,然後向該私密選擇的數字提交承諾,都使用某種共識演算法就某些承諾達成一致,然後全部透露其選擇的數字,得出乙個 對顯示的數字達成共識,並對顯示的數字進行xor作為協議的輸出。它是不可 的,並且與...