ECDSA橢圓曲線數字簽名演算法
ECDSA橢圓曲線數字簽名演算法
符號說明
- \(F_p\): \(y^2 = x^3 + ax + b, (4a^3+27b^2)\mod p \ne 0, (x,y)\in F_p\);
- \(F_{2^m}\): \(y^2 + xy = x^3 + ax^2+b, b \ne 0, (x,y) \in F_{2^m}\);
- \(G\): 橢圓曲線域引數的基點或生成子;
- \((x_P, y_P)\): 橢圓曲線點\(P\)的座標表示;
- \((r,s)\): 數字簽名, 整數對;
- \(Q\): 公鑰;
- \(d\): 私鑰, \(Q = d\cdot G\);
- \(\mathcal{O}\)
- \(n\): 素數, 生成子\(G\)的階;
- \(E(F_q)\): 定義在\(F_q\)域上的橢圓曲線;
- \((a, b)\): 橢圓曲線的係數;
- \(q\): 有限域的大小;
- \(truncate_l(X)\): 取位字串\(X\)的最左邊\(l\)位/位元組;
- 域引數:
- \(q\);
- \(a\);
- \(b\);
- \(x_G\);
- \(y_G\);
- \(n\);
- \(SEED\): (可選), 用於生成可驗證的隨機域引數的位字串;
- \(h\): (可選), 餘因子\(h=|E|/n\);
資料轉換
整數和八位串之間的轉換
記有自然數\(x\), 與其對應的八位串記為\(M\)
- \(x = \sum_{i=1}^{k}2^{8\cdot (k-i)} \cdot m_i\);
- \(M = m_1 || m_2 || \dots || m_k\);
域元素轉為八位串
記有域元素\(\alpha, \alpha \in F_q\), 將其轉換為八位串\(M\):
- \(t = \lceil \log_2(q) \rceil, l = \lceil t/8 \rceil\);
- \(q \mod 2 = 1\):
- \(\alpha \in [0,q-1]\)的整數, 按照整數將其轉為八位串;
- \(q \mod 2 = 0, q = 2^m\):
- \(\alpha = s_1 || s_2 || \dots || s_m\);
- \(S = 0||\dots||0, bitslen(S) = 8\cdot l - m\);
- \(M = S || s_1 || s_2 || \dots || s_m\);
八位串轉為域元素
記有域\(F_q\), 八位串\(M, len(M) = l, l = \lceil t/8 \rceil, t = \lceil \log_2(q) \rceil\), 將其轉為域元素\(\alpha\):
- \(q \mod 2 = 1\):
- 將\(M\)轉為整數\(x\), 若\(x \in [0,q-1]\), 則\(\alpha = x\);
- \(q \mod 2 = 0, q = 2^m\):
- \(M = S || m_1 || m_2 || \dots || m_m, bitslen(S) = 8\cdot l - m\);
- \(\alpha = m_1 || m_2 ||\dots ||m_m\);
域元素轉為整數
記有域元素\(\alpha \in F_q\), 將其轉為整數\(x\):
- \(q \mod 2 = 1\):
- \(x = \alpha\);
- \(q \mod 2 = 0, q = 2^m\):
- \(\alpha = s_1 || s_2 || \dots || s_m\);
- \(x = \sum_{i=1}^{m} 2^{m-i} s_i\);
曲線點轉為八位串
無窮遠點\(\mathcal{O}\)轉為\(M = 0x00\);
記有橢圓曲線\(E(F_q)\)上的非無窮遠點\(P=(x_P, y_P)\), 將其轉為八位串\(M\):
- 將域元素\(x_P\)轉為八位串\(M_x\);
- 若以壓縮形式表示點, 則:
- 計算壓縮形式\((x_P, z_P)\);
- \(z_P = 0\):
- \(M = 0x02 || M_x\);
- \(z_P = 1\):
- \(M = 0x03 || M_x\);
- 若以非壓縮形式表示點, 則:
- 將域元素\(y_P\)轉為八位串\(M_y\);
- \(M = 0x04 || M_x || M_y\);
- 若以混合形式表示點, 則:
- 將域元素\(y_P\)轉為八位串\(M_y\);
- 計算\(z_P\);
- \(z_P = 0\):
- \(M= 0x06 || M_x || M_y\);
- \(z_P = 1\):
- \(M= 0x07 || M_x || M_y\);
八位串轉為曲線點
記有域\(F_q\), 和合法的八位串\(M\), 將其轉為點$P=(x_P, y_P);:
- \(l = \lceil \log_2(q) / 8 \rceil\);
- \(len(M) = 1 \land M = 0x00\):
- \(P = \mathcal{O}\);
- \(len(M) = l + 1\):
- \(M = S || M_x, len(S) = 1\);
- 驗證\(S = 0x02 \lor S = 0x03\);
- \(S = 0x02\):
- \(z_P = 0\);
- \(S = 0x03\);
- \(z_P = 1\);
- 將八位串\(M_x\)轉為域元素\(x_P\);
- 壓縮形式的點\((x_P, z_P)\)轉為點\((x_P, y_P)\);
- \(len(M) = 2\cdot l + 1\):
- \(M = S || M_x || M_y, len(S) = 1, len(M_x) = l\);
- 驗證\(S = 0x04 \lor S = 0x06 \lor S = 0x07\);
- 將八位串\(M_x\)轉為域元素\(x_P\);
- 將八位串\(M_y\)轉為域元素\(x_P\);
- \(S = 0x06 \lor S = 0x07\):
- \(S = 0x06\)
- \(z_P = 0\)
- \(S = 0x07\)
- \(z_P = 1\)
- 由\((x_P, y_P)\)計算\(z_{P}^{'}\), 驗證\(z_P = z_{P}^{'}\);
- 由\((x_P, z_P)\)計算\((x_P, y_{P}^{'})\), 驗證\(y_P = y_{P}^{'}\);
- \(S = 0x06\)
簽名
- 記有位字串訊息\(M\);
- 由域引數生成臨時金鑰對\((k, R)\);
- 將\(x_R\)轉為整數\(j\);
- \(r = j \mod n, r \ne 0\);
- \(H = Hash(M)\);
- 將\(H\)轉為整數\(e\):
- \(E = truncate_l(H), l = \min(log_2(n), bitslen(H))\);
- 將位字串轉為整數\(e\);
- \(s = k^{-1}\cdot (e+d\cdot r) \mod n,\quad s \ne 0\);
- 輸出\((r, s), r\in [1,n-1], s\in [1,n-1]\);
驗證
通過公鑰驗證
- 記收到訊息\(M'\), 簽名\((r', s')\);
- 驗證\((r' \in [1,n-1]) \land (s' \in [1,n-1])\);
- \(H' = Hash(M')\);
- 將\(H'\)轉為整數\(e\):
- \(E = truncate_l(H'), l = \min(log_2(n), bitslen(H))\);
- 將位字串\(E\)轉為整數\(e\);
- \(u_1 = e' \cdot (s')^{-1} \mod n, u_2 = r' (s')^{-1}\mod n\);
- 計算橢圓曲線點\(R=(x_R, y_R) = u_1\cdot G + u_2\cdot Q\);
- 驗證\(R \ne \mathcal{O}\);
- 將\(x_R\)轉為整數\(j\);
- \(v = j\mod n\);
- 驗證\(v = r'\);
通過私鑰驗證
- 記收到訊息\(M'\), 簽名\((r', s')\);
- 驗證\((r' \in [1,n-1]) \land (s' \in [1,n-1])\);
- \(H' = Hash(M')\);
- 將\(H'\)轉為整數\(e\):
- \(E = truncate_l(H'), l = \min(log_2(n), bitslen(H))\);
- 將位字串\(E\)轉為整數\(e\);
- \(u_1 = e' \cdot (s')^{-1} \mod n, u_2 = r' (s')^{-1}\mod n\);
- \(k' = (u_1 + u_2\cdot d) \mod n\);
- \(R = k'\cdot G\);
- 驗證\(R \ne \mathcal{O}\);
- \(v = j\mod n\);
- 驗證\(v = r'\);
橢圓曲線域引數
點壓縮
記由橢圓曲線上的一點\(P=(x_P, y_P)\), 則點可以壓縮為\(x_P\)和\(y_P\)的某些位\(z_P\);
- \(rightmost_l(y)\)表示\(y\)的最右邊的\(l\)位;
- \(leftmost_l(y)\)表示\(y\)的最左邊的\(l\)位;
域\(F_p\)上點壓縮
\(P=(x_P,y_P), y^2 = x^3 + a\cdot x+b,\quad x,y\in F_p,\ z_P = rightmost_1(y_P)\);
- 已知\((x_P, z_P)\)求\(y_P\);
- \(\alpha = x_P^3 + a\cdot x_P + b \mod p\);
- \(\beta = \sqrt{\alpha} \mod p\);
- \(y_P = \beta\quad if\ rightmost_1(\beta)=y_P\quad else\ y_P = p-\beta\);
域\(F_{2^m}\)上點壓縮
\(P=(x_P,y_P), y^2 + x\cdot y = x^3 + a\cdot x^2 + b,\quad x,y\in F_{2^m}\). 若\(x_P=0\), 則\(z_P=0\). 否則, \(z_P = rightmost_1(y_P\cdot x_{P}^{-1})\);
- 已知\((x_P, z_P)\)求\(y_P\);
- 若\(x_P=0\), \(y_P = b^{2^{m-1}}\);
- 若$x_P\ne 0 $:
- \(\alpha = x_P + a + b\cdot x_P^{-2}\);
- \(\beta^2 + \beta = \alpha\);
- \(z_{P}^{'} = rightmost_1(\beta)\);
- \(z_{P}^{'} \ne z_P\);
- \(\beta = \beta + g\), 其中\(g\)是乘法單位元;
- \(y_P = x_P\cdot \beta\);
保證橢圓曲線安全性的一些必要條件
MOV條件
Menezes-Okamoto-Vanstone(MOV): \(F_q \rightarrow F_{q^B}, B\ge 1\), ANS X9.62中選擇\(B\)大於等於100;
- 給定MOV閾值\(B\), 素數\(q\), 素數\(n, n=|E(F_q)|\), 驗證MOV條件是否合法:
- \(t = 1\);
for i in 1..=B
:- \(t = t\cdot q \mod n\);
return false
, if \(t = 1\);
return true
;
異常條件(The Anomalous condition)
若\(|E(F_q)| = q\), 則稱定義在\(F_q\)上的橢圓曲線\(E(F_q)\)是\(F_q-anomalous\), 該種情況下橢圓曲線的離散對數問題很容易被解出.
- 給定\(E(F_q)\), 及橢圓曲線的階\(u=|E(F_q)|\), 驗證是否滿足Anomalous條件:
return u != q
;
橢圓曲線的選擇
可驗證隨機橢圓曲線
給定隨機種子\(SEED\), \(t=bitslen(HashVal)\), \(|F_q|=q\), 求橢圓曲線的係數\((a,b)\);
- \(m = \lceil \log_2(q) \rceil\);
- \(s = \lfloor (m-1)/t \rfloor\);
- \(k = m - st - (q \mod 2)\);
- \(H = Hash(SEED)\);
- \(H\)轉為整數\(e\);
- \(c_0 = e \mod 2^k\);
for j in 1..=s
:- \(c_j = Hash((SEED + j)\mod 2^g)\)
- \(c = c_0\cdot 2^{ts} + c_1\cdot 2^{t\cdot (s-1)}+\dots + c_s\);
- 將整數\(c\)轉為域元素\(r\);
- 從\(F_q\)中隨機選擇一個元素\(a\);
- \(q \mod 2 = 0\):
- \(b = r\);
return error
, if \(b = 0\);
- \(q \mod 2 = 1\):
- \(b^2\cdot r = a^3\)
return error
, if \(4\cdot a^3 + 27\cdot b^2 = 0\);
return (a,b)
;
橢圓曲線的驗證
- 給定橢圓曲線\(E(F_q, a, b)\), 可選的種子\(SEED\), 驗證該橢圓曲線是否合法:
- \(q\)是奇數, 若:
- \(q\)不是素數:
return false
;
- \(a \notin [0,q-1], b \notin [0,q-1]\):
return false
;
- \(4\cdot a^3 + 27\cdot b^2 = 0\):
return false
;
- \(q\)不是素數:
- \(q\)是偶數, 若:
- \(q\)不滿足\(q = 2^m\), \(m\)是素數;
return false
;
- \(bitslen(a) \ne m, bitslen(b) \ne m\):
return false
;
- \(q\)不滿足\(q = 2^m\), \(m\)是素數;
- 若\(SEED\)提供, 驗證更具上一節的橢圓曲線生成演算法生成\((a', b')\):
return a=a' && b=b'
;
return true
;
- \(q\)是奇數, 若:
基點的選擇
可驗證隨機基點
給定隨機種子\(SEED\), 整數計數器\(base\), \(hashlen = bitslen(HashVal)\), 域大小\(q\), 餘因子\(h\), 求基點\(x_G, y_G\);
- \(element = 1\);
loop
:- 將計數器\(base\)的值和\(element\)轉為位字串\(Base, Element\);
- \(H = Hash("Base point" || Base || Element || SEED)\);
- \(H\)轉為整數\(e\);
- \(element = element + 1\);
break
, if \(\lfloor e/2\cdot q \rfloor \ne \lfloor 2^{hashlen} / (2\cdot q) \rfloor\);
- \(t = e \mod (2\cdot q)\);
- \(x = t\mod q, z = \lfloor t/q \rfloor\);
- \(x\)轉為域元素\(x_G\);
- 由\((x_G, z)\)計算出\(y_G\);
- 輸出\((x_G, y_G)\);
基點的驗證
給定域引數, 驗證基點\(G\)是否合法;
- \(G = \mathcal{O}\):
return false
;
- \(q\)奇數, 若:
- \(x_G \notin [0,q-1], y_G \notin [0,q-1]\):
return false
;
- \(y_{G}^2 \ne x_{G}^3 + a\cdot x_G + b\):
return false
;
- \(x_G \notin [0,q-1], y_G \notin [0,q-1]\):
- \(q=2^m\)偶數, 若:
- \(bitslen(x_G) \ne m, bitslen(y_G) \ne m\):
return false
;
- \(y_{G}^2 + x_G\cdot y_G \ne x_{G}^3 + a\cdot x_{G}^2 + b\):
return false
;
- \(bitslen(x_G) \ne m, bitslen(y_G) \ne m\):
- \(n\cdot G \ne \mathcal{O}\):
return false
;
- 若提供了隨機種子\(SEED\):
- \(base = 1\):
loop
:return false
, if \(base \gt 10\cdot h^2\);- 通過\(SEED\)和\(base\)生成基點\(R=(x,y)\);
- \(G' = h\cdot R\);
- \(base = base + 1\);
break
, if \(n\cdot G' = \mathcal{O}\);
return G' = G
;
return true
;
橢圓曲線域引數的選擇
生成隨機種子\(SEED\), 生成基點/曲線係數;
EC域引數的驗證
給定安全級別\(s\);
- \(n \lt \max(2^{2\cdot s - 1}, 2^{160})\):
return false
;
- \(n\)不是素數:
return false
;
- 橢圓曲線\(E(F_q, a, b)\)不合法:
return false
;
- \(h' = \lfloor (q^{1/2} + 1)^2 / n\);
- 如果域引數提供了\(h\), 若\(h \ne h'\):
return false
;
- \(h' \gt 2^{s/8}\):
return false
;
- MOV條件不合法:
return false
;
- Anomalous條件不合法:
return false
;
- 基點\(G\)不合法:
return false
;
return true
;
EC域引數的生成
給定安全級別\(s\), 和可選的一些限制: 最大的餘因子值\(h_max\), 準素性驗證中的素除數界\(I_max\), MOV條件的閾值\(B\);
- 生成\(SEED\);
- 選擇一個符合安全級別的域大小\(q\);
- 生成\(E(F_q, a, b)\);
- 計算橢圓曲線的大小\(u=|E|\);
- 生成\(n, h\);
- 生成基點\(G\);
- 驗證域引數的合法性;
- 輸出域引數;
橢圓曲線金鑰對
\((d, Q), d\in [1,n-1], Q = d\cdot G\);
橢圓曲線公鑰驗證
給定公鑰\(Q\)和已經驗證正確的域引數, 驗證\(Q\)的合法性:
- \(Q = \mathcal{O}\):
return false
;
- \(q \mod 2 = 1\):
- \(x_Q \not in [0,q-1], y_Q \notin [0,q-1]\):
return false
;
- \(y_Q^2 \ne x_Q^3 + a\cdot x_Q + b\):
return false
;
- \(x_Q \not in [0,q-1], y_Q \notin [0,q-1]\):
- \(q \mod 2 = 0, q = 2^m\):
- \(bitslen(x_Q) \ne m, bitslen(y_Q) \ne m\):
return false
;
- \(bitslen(x_Q) \ne m, bitslen(y_Q) \ne m\):
- \(y_Q^2 + x_Q \cdot y_Q \ne x_Q^3 + a\cdot x_Q^2 + b\):
return false
- \(n\cdot Q \ne \mathcal{O}\):
return false
;
- \(n\cdot Q = \mathcal{O}\):
return true
;
橢圓曲線金鑰對的生成
給定已經驗證正確的域引數, 金鑰對\((d, Q)\)生成如下:
- 隨機選擇一個整數作為私鑰\(d\in [1,n-1]\);
- 計算公鑰\(Q = d\cdot G\);
素性
概率素性測試-ProbabilisticPrimalityTest
由於早期部落格符號不統一, 這裡重新描述下:
- 記由一個奇數\(n\), 和正整數\(T\), 現需判斷\(n\)是合數, 還是可能是一個素數(注意這裡是可能, Miller-Rabin測試出錯的概率和測試次數有關, 至多為\(2^{-T}\));
- 計算非負整數\(v\)和奇正數\(w\), 滿足\(n-1 = 2^v \cdot w\);
- rust:
for j in 1..=T
:- 隨機選擇一個整數\(a, a\in [2, n-1]\);
- \(b = a^w \mod n\);
continue
, if \(b = 1\) or \(b = n-1\);- \(cnt = 0\);
for i in 1..=(v-1)
:- \(b = b^2 \mod n\);
break
, if \(b = n-1\);return 合數
if \(b = 1\);- \(cnt = cnt + 1\);
return 合數
, if \(cnt = v-1\);
return 可能是素數
;
準素性(near primality)測試
-
概念說明:
- 記有正整數\(I_{max}\), 若正整數\(h\)的每個素除數都不超過\(I_{max}\), 那麼稱\(h\)是\(I_{max}-smooth\);
- 記有兩個素數\(p_1, p_2\), 有\(p=p_1\cdot p_2\), 那麼稱\(p\)是準素數;
- 記有正整數\(r_{min}\), \(I_{max}-smooth\)的正整數\(h\), 及可能是素數的正整數\(n, n\ge r_{min}\). 若正整數\(u\)滿足\(u=h\cdot n\), 那麼\(u\)是一個準素數;
-
準素性測試:
- 記有正整數\(r_{min}, I_{max}, u\), 判斷\(u\)是否是一個準素數:
- \(n = u, h = 1\);
for i in 2..=I_max
:- while \(n / i \gt 0\):
- \(n = n / i,\quad h = h\cdot i\);
return 非準素數
, if \(n \lt r_{min}\);
- while \(n / i \gt 0\):
return (準素數, h, n)
, if \(n\)滿足概率素性測試;return 非準素數
;
- 記有正整數\(r_{min}, I_{max}, u\), 判斷\(u\)是否是一個準素數:
參考資料
- ANS X9.62-2005;