1. 程式人生 > >比特幣系統採用的公鑰密碼學方案和ECDSA簽名演算法介紹——第一部分:原理

比特幣系統採用的公鑰密碼學方案和ECDSA簽名演算法介紹——第一部分:原理

ECC演算法是基於有限域的橢圓曲線上的數學演算法。關於ECC演算法基本原理的介紹,請參考《ECC加密演算法入門介紹》(http://www.8btc.com/eccmath),本文重點介紹Bitcoin系統中採用的公鑰密碼學方案和簽名演算法的實現細節。

一、 公鑰(pubkey)、私鑰(privkey)是什麼

公開金鑰加密(public-key cryptography,也稱為非對稱(金鑰)加密),是指存在一對數學演算法相關的金鑰,使用其中一個金鑰加密後所得的資訊,只能用另一個金鑰才能解密。如果其中一個公開後並不會危害到另外一個的祕密性質,則稱公開的金鑰為公鑰,不公開的金鑰為私鑰。

  公鑰的主要作用:加密;驗證簽名。


  私鑰的主要作用:簽名;解密。

特性:

  • 通過私鑰可以計算出公鑰,反之則不行。
  • 公鑰加密:公鑰加密的內容可以用私鑰來解密——只有私鑰持有者才能解密。
  • 私鑰簽名:私鑰簽名的內容可以用公鑰驗證。公鑰能驗證的簽名均可視為私鑰持有人所簽署。

以上特性通過數學演算法來保證。公鑰密碼學的實現方案有很多種, 常見的有RSA、ElGamal、、迪菲-赫爾曼金鑰交換協議中的公鑰加密演算法、橢圓曲線加密演算法(ECC)。

網銀系統中主要使用的是RSA方案。比特幣系統則使用的是ECC方案,在核心實現中並不使用加密,只使用了簽名演算法來確保交易的真實性和所有權的認證。

二、橢圓曲線加密演算法(ECC)簡介

ECC方案通常包含有三方面內容,數字簽名方案、加密和金鑰傳輸方案、以及金鑰協商方案。本文只涉及到比特幣系統所使用的數字簽名方案。

(一)有限域(Finite Field):

(最近有一些關於量子攻擊的討論中涉及到這一概念,有一定數學基礎的和毫無數學基礎的可以跳過這一小節)

域(Field)的特性是集合F中的所有元素經過定義後的加法和乘法運算,所得結果仍包含於F(在加法和乘法上封閉)。無限域的元素個數無限,比如有理數域、實數域。
有限域的元素個數有限,這就出現一個問題,假設F為從0至9的整數集合,那麼5,6都屬於F,但常規的加法定義5+6=11,11不屬於F。因而,有限域需要定義加法和乘法,使其滿足對加法和乘法的封閉。

目前已發現,當且僅當元素個數q為質數或某個質素的n次冪時,必有一個元素個數為q的有限域存在。另外,對於每一個符合這一條件的q值,都恰有一個有限域。含有q個元素的有限域記作:Fq。
ECC方案中只使用了兩類有限域:一種稱為質數有限域Fp,其中 q = p, p 為一個質數;另一種稱為基於特徵值2的有限域F2^m,其中q = 2^m , m > 1。
比特幣系統使用的是第一種。
Fp是一個{0,1…,p-1}的整數集合,有限域Fp中定義了
加法:a + b ≡ r (mod p)
乘法:ab ≡ s(mod p).

(二)基於有限域Fp的橢圓曲線域E(Fp):

橢圓曲線:y^2 ≡ x^3 + ax + b (mod p)
當:a, b ∈ Fp 且滿足 4a^3+27b^2 ≠ 0 (mod p). , x, y ∈ Fp時,這條曲線上的點的集合P=(x,y)就構成了一個基於有限域Fp的橢圓曲線域E(Fp),元素個數記作#E(Fp)。

問:這和比特幣系統有什麼關係嗎?
答:公鑰即為該曲線上的某個點Q=(x,y)的二進位制輸出格式。公鑰可以壓縮,是因為y可以根據x通過曲線函式計算出來。

(三)橢圓曲線域E(Fp)的描述引數:

E : y^2 ≡ x^3 + ax + b (mod p)

為描述特定的橢圓曲線域,需明確六個引數:T = (p, a, b, G, n, h)

p: 代表有限域Fp的那個質數
a,b:橢圓方程的引數
G: 橢圓曲線上的一個基點G = (xG, yG)
n:G在Fp中規定的序號,一個質數。
h:餘因數(cofactor),控制選取點的密度。h = #E(Fp) / n。

比特幣系統選用的secp256k1中,引數為
p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
= 2^256 − 2^32 − 2^9 − 2^8 − 2^7 − 2^6 − 2^4 − 1

a = 0, b = 7

G =04 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9
59F2815B 16F81798 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448
A6855419 9C47D08F FB10D4B8

n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
h = 01

問:n和比特幣系統有什麼關係?
答:比特幣系統規定私鑰的取值範圍最大不能超過n。

(四)公鑰和私鑰:

隨機從[1,n-1]中選取一個數d, 計算Q = dG
其中,d就是私鑰,而Q即為公鑰

這一算式看起來很簡單,但這怎樣保證由Q不能算出d呢?
有限域中的加法和乘法是有特殊規定的。基於Fp的橢圓曲線點的集合域中,加法運算是:

不同的點相加: (x1, y1) ∈ E(Fp) , (x2, y2) ∈ E(Fp), x1 ≠x2
(x1, y1) + (x2, y2) = (x3, y3),其中,
x3 ≡ λ^2 − x1 − x2 (mod p), y3 ≡ λ(x1 − x3) − y1 (mod p), 而λ≡ (y2 − y1)/(x2 − x1)(mod p).

相同點疊加: (x1, y1) ∈ E(Fp) ,  y1 ≠ 0.
(x1, y1) + (x1, y1) = (x3, y3), 其中,
x3 ≡ λ^2 − 2×1 (mod p), y3≡ λ(x1 − x3) − y1 (mod p), andλ≡(3×1^2+ a)/2y1(mod p).

dG是一個標量乘法,可以轉化為加法運算,如果有愛好者想由公鑰逆推出私鑰,可以根據這些公式來嘗試一下(筆者本人已經放棄了這種努力)。

三、 橢圓曲線數字簽名演算法(ECDSA):

使用者的金鑰對:(d, Q);(d為私鑰,Q為公鑰)
待簽名的資訊:M;
簽名:Signature(M) = ( r, s)

簽名過程:

1、根據ECC演算法隨機生成一個金鑰對(k, R), R=(xR, yR)
2、令 r = xR mod n,如果r = 0,則返回步驟1
3、計算 H = Hash(M)
4、按照資料型別轉換規則,將H轉化為一個big endian的整數e
5、s = k^-1 (e + rd) mod n,若s = 0, 則返回步驟1
6、輸出的S =(r,s)即為簽名。

驗證過程:

1、 計算 H = Hash(M)
2、按照資料型別轉換規則,將H轉化為一個big endian的整數e
3、計算 u1 = es^-1 mod n, u2 = rs^-1 mod n
4、計算 R = (xR, yR) = u1G + u2Q, 如果R = 零點,則驗證該簽名無效
5、令 v = xR mod n
6、若 v == r,則簽名有效,若 v ≠ r, 則簽名無效。