數字簽名是密碼學領域的第二個非常重要的概念,第一個是 hash 算法,前面我們已經花了兩篇文章做了瞭解,見 密碼學之 Hash 算法 和 Hash 指針和數據結構(區塊鏈和默克爾樹),其在互聯網安全領域以及區塊鏈系統中都有着非常重要的應用。

可以把數字簽名看成傳統簽名在數字領域的一個延伸,特徵如下:

數字簽名和 ECDSA 算法

  1. 簽名不可以僞造,但是可以被驗證

  2. 簽名和特定的文檔緊密相關

也就是說,雖然我們的簽名是以數字的形式表達的,但和傳統紙筆簽名一樣,筆跡不能被輕易的僞造,並且我們根據筆跡就可以知道是誰籤的。同時,人們也很難有方法將一處簽名嫁接到另外一處。

接着看一下數字簽名的 API 表達:

數字簽名和 ECDSA 算法

這裏有三個重要的操作:

  1. 生成祕鑰對

  2. 簽名

  3. 驗籤

第一步主要是利用一些工具生成公、私鑰,至於什麼是公鑰,什麼是私鑰,以及它們之間的關係,下一篇關於 PKI 體系的文章我們會有一個系統的認識。這裏只要明確,私鑰本質上就是一串隨機數,你可以通過擲骰子算出這段隨機數,但是更加保險的做法是通過一些成熟的庫工具。而公鑰是基於某種算法,通過私鑰推算出來的。

一般情況下,公鑰可以任意公佈,但是私鑰需要嚴加保管。私鑰用來對一段信息進行簽名。而公鑰可以驗證這段簽名的合法性以及身份(我們通常都會有 public keys as identities 的說法):

數字簽名和 ECDSA 算法

顯然,理論上簽名是不應該可以被僞造,否則我們做的所有工作都失去了意義。倘若有壞人鑽了空子非要去僞造簽名,會有成功的機會嗎?先看一下壞人掌握的信息:

  1. 公鑰

  2. 已經簽過名的信息

ok,爲了模擬這個場景,有人很無聊的發明了下面這個遊戲 …

數字簽名和 ECDSA 算法

假設圖中的 challenger 是我,那麼我在生成公鑰和私鑰之後,將公鑰公佈出去。那壞人,圖中的 attacker 就知曉了我的公鑰。同時,我不斷的給這個壞人發送附帶了我的數字簽名的信息,讓他分析直到他聲稱他已經通過所掌握的信息,模擬出了我的簽名,並將其發送給我驗證。

但理論上,無論我選擇的是什麼簽名算法,attacker 應該永遠不會模擬出我的簽名。

回到工業實現上,比特幣等區塊鏈系統通常使用橢圓曲線數字簽名算法標準是 ECDSA,其理論基礎是基於橢圓曲線離散對數問題的難解性,基本的簽名和驗簽過程如下:

簽名:

  1. 選擇一條橢圓曲線 Ep(a,b),和基點 G

  2. 選擇私有密鑰 k (k

  3. 產生一個隨機整數 r (r
  4. 將原數據和點 R 的座標值 x,y 作爲參數,計算 SHA1 做爲 hash,即 Hash=SHA1(原數據 ,x,y)

  5. 計算 s≡r – Hash * k (mod n)

  6. r 和 s 做爲簽名值,如果 r 和 s 其中一個爲 0,重新從第 3 步開始執行

驗籤:

  1. 接受方在收到消息 (m) 和簽名值 (r,s) 後,進行以下運算

  2. 計算:sG+H(m)P=(x1,y1), r1≡ x1 mod p

  3. 驗證等式:r1 ≡ r mod p

各個主流語言都會有對 ECDSA 標準的實現,如 Golang 的包 crypto/ecdsa,Java 的 java.security 包。比特幣 btcd 和以太坊 geth 也有對應 secp256k1 標準和實現。


歡迎讀者加入哈希 1024 區塊鏈社區微信羣,進行更多的區塊鏈技術交流,可關注本公衆號,在後臺回覆“哈希”即可。