橢圓曲線ECC ECDH原理&& javacard實現


橢圓曲線原理:

橢圓曲線的圖像並不是橢圓形,橢圓曲線源自於求橢圓弧長的橢圓積分的反函數。

定義:

橢圓曲線可用下列方程來表示,其中a,b,c,d為系數。

E: y2 =ax3 + bx2 +cx +d

橢圓曲線運算:(相當於交換群)

A+B:

過曲線上兩點A,B畫一條直線,找到直線與橢圓曲線的的交點,將該交點關於x軸對稱位置的點定義為A+B。

A+A:

畫出曲線在A點的切線,找到該切線與橢圓曲線的交點,將該交點關於x軸對稱位置的點定義為A+A,即2A。

-A:

A點關於X軸對稱位置的點定義為-A。

A+(-A)怎樣定義?

認為A和-A間的這條直線在無窮遠處相交,這個點圖像上畫不出來,記為O。

基於上邊的運算,如果有橢圓曲線上一個點G,可以求2G,3G,。。。點的坐標。就是說給定G,求xG並不困難。但反過來很難!(橢圓曲線上的離散對數問題)

橢圓曲線上的離散對數問題

本質上就是“已知點xG求數x的問題”。

密碼學中的橢圓曲線

密碼學中的橢圓曲線運算不是在光滑曲線上進行,並不能使用上面的實數域上的橢圓曲線,因為
1. 實數域上的橢圓曲線是連續的,有無限個點,密碼學要求有限點。
2. 實數域上的橢圓曲線的運算有誤差,不精確。密碼學要求精確。

所以我們需要引入有限域上的橢圓曲線。就是說不是在實數域R上,而是在有限域Fp上。
(x,y坐標的取值只能在有限域Fp中取)

Fp中只有p(p為素數)個元素0,1,2 …… p-2,p-1;
Fp 的加法(a+b)法則是 a+b≡c (mod p);即,(a+c)÷p的余數 和c÷p的余數相同。

比特幣中ECDSA使用的橢圓曲線參數:secp256k1

有限域Fp定義:
p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
= 2256 - 232 - 29 - 28 - 27 - 26 - 24 - 1

Fp上的曲線E:y2 = x3 + ax + b定義如下:

a = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
b = 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000007

壓縮形式(1字節壓縮標志位+32字節x坐標)的基點G是:

G = 02 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798

未壓縮形式(1字節壓縮標志位+32字節x坐標+32字節y坐標):

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

參數n,它是使得 nG=0 的最小正整數:

n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141

參數h,它是橢圓曲線群的階跟由G生成的子群的階的比值。是設計secp256k1時使用的參數,在具體實現中使用這個參數主要是出於安全性考慮,忽略它不影響理解。

h = 01

屏幕快照 2018-07-28 上午10.48.40

私鑰公鑰地生成過程:

用戶隨機生成一個小於 n 的大整數 k ,這就是私鑰。
然后計算 Q=kG ,這就是公鑰(注意,公鑰是橢圓曲線上的一個點)。

ECDH過程:

假設公私鑰是用於密鑰交換,那么步驟如下(這里的乘法是指橢圓曲線上點的乘法):

part1:

小紅生成私鑰kA,將它乘以基點G得到公鑰QA,即 kA *G=QA
小明生成私鑰kB,將它乘以基點G得到公鑰QB,即 kB *G=QB

part2:

小紅計算 ( xk, yk ) = kA *QB, xk即為交換得到的密鑰。
小明計算 ( xk, yk ) = kB *QA, xk即為交換得到的密鑰。

最后,小紅跟小明得到的密鑰是相同的。

由以上過程,ECDH的part2部分最終交換得到的密鑰是只用到曲線上的點32字節的x坐標值,是沒用到y坐標的。
而part1部分,這個公鑰QA則必須是全的xy坐標都有。

注:ledger源碼中由32字節ECC私鑰生成65字節(1+32x+32y)ECC公鑰的過程實際只用到了part1,只要得到Q的x和y坐標。

javacard中的ECDH

javacard.security.KeyAgreement

KeyAgreement類是密鑰協商算法的基類,例如Diffie-Hellman和EC Diffie-Hellman [IEEE P1363]。 KeyAgreement算法的實現必須擴展此類並實現所有抽象方法。撕裂或卡重置事件將初始化的KeyAgreement對象重置為先前通過調用init()初始化時所處的狀態。

在用這個類實現ECDH時,
首先,

private KeyAgreement keyAgreement;

keyAgreement=KeyAgreement.getInstance(KeyAgreement.ALG_EC_SVDP_DH_PLAIN_XY,false);
getInstance

功能是創建所選算法的KeyAgreement對象實例。

public static final KeyAgreement getInstance(byte algorithm,
                       boolean externalAccess)
                                      throws CryptoException

algorithm - 所需的密鑰協商算法:例如:ALG_EC_SVDP_DH_PLAIN_XY
屏幕快照 2018-07-28 下午12.42.24

externalAccess - 如果為true,則表示實例將在多個applet實例之間共享,並且當KeyAgreement實例的所有者不是當前選定的applet時,也將訪問KeyAgreement實例(通過Shareable接口)。如果為true,則實現不得為內部數據分配CLEAR_ON_DESELECT瞬態空間。

然后,

keyAgreement.init(privateKey)

privateKey存了對應於小紅的私鑰kA

注意:
這個privateKey一定要在之前設定好secp256k1對應的參數(ledger源碼中定義了Secp256k1類,只需調用Secp256k1.setCommonCurveParameters(privateKey)設置參數),
並且也放入了私鑰值kA(調用setS()來存)

init()

功能是使用給定的私鑰初始化對象。
檢查密鑰與KeyAgreement算法的一致性。例如,密鑰類型必須匹配。對於橢圓曲線算法,key必須表示曲線域參數上的有效點。其他關鍵組件/域參數強度檢查是特定於實現的。

接着,就是流程中小紅生成QA(QA結果存放在publicPoint中),

keyAgreement.generateSecret(Secp256k1.SECP256K1_G, (short)0, 
(short)Secp256k1.SECP256K1_G.length, publicPoint, publicPointOffset);
generateSecret

函數generateSecret就是實現密鑰交換中的這兩部分的曲線上乘法,例如kA*G=QA

輸出的結果根據所選擇的算法不同是不同的,具體的:
帶有_PLAIN:輸出結果就是原始的,與之對應不帶有PLAIN的則是輸出將原始結果通過SHA-1散列后得到的20字節的結果。

帶有_XY:輸出結果是未壓縮完整的結果QA(65字節),與之對應的不帶有_XY的則是壓縮形式的結果(只有QA的x坐標,即32字節)
帶有_DHC:和帶有_DH的輸出是一樣的,只是DHC是 with cofactor multiplication and compatibility mode

注:綜上,ledger中源碼應選擇同時帶有_PLAIN和_XY的算法,即 ALG_EC_SVDP_DH_PLAIN_XY


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM