ECC加密算法C简单实现
ECC加密算法 c完成
ECC加密算法的理解
本文主要參照:ECC橢圓曲線加解密原理詳解(配圖)
3.2 ECC算法
3.2.1 ECC算法簡介
與 RSA(Ron Rivest,Adi Shamir,Len Adleman 三位天才的名字)一樣,ECC(Elliptic Curves Cryptography,橢圓曲線加密)也屬于公開密鑰算法。
3.2.2 ECC算法中的關(guān)鍵變量
① 基點(diǎn):基點(diǎn)G,G為橢圓曲線Ep(a,b)上的點(diǎn)
② 階:如果橢圓曲線上一點(diǎn)P,存在最小的正整數(shù)n使得數(shù)乘n P = O ∞ ,則將n稱為P的階,若n不存在,則P是無限階的.
③ 公鑰K:則給定私鑰k和基點(diǎn)G,根據(jù)加法法則,計(jì)算K很容易但反過來,給定K和G,求k就非常困難。因?yàn)閷?shí)際使用中的ECC原則上把p取得相當(dāng)大,n也相當(dāng)大,要把n個(gè)解點(diǎn)逐一算出來列成上表是不可能的。
3.2.4 有限域上的橢圓運(yùn)算算法
根據(jù)3.1.2的相關(guān)資料,我們只需要用代碼實(shí)現(xiàn)算術(shù)式,但編程語言中分?jǐn)?shù)和負(fù)數(shù)是不能對一個(gè)數(shù)取余的,因此我們需要進(jìn)行一些轉(zhuǎn)換和計(jì)算來將取余的值算出來。
圖3-6 橢圓曲線上的加法運(yùn)算
如圖3-6中的k的計(jì)算,當(dāng)P等于Q時(shí)需要注意y1可能為0,后面計(jì)算階會(huì)對這種情況進(jìn)行處理說明;計(jì)算k時(shí):先判斷分子分母的符號(hào),判斷是否同號(hào),再將其全部轉(zhuǎn)化為正數(shù),然后判斷分子大還是分母大,來計(jì)算最大因子,然后化簡,化簡后再來根據(jù)分母當(dāng)做這個(gè)b × b ? 1 ≡ 1 ( m o d p )公式的b;來將b的-1次方算出,然后根據(jù)分子分母是否同號(hào),給他們附上符號(hào),這樣就是分母乘以分子的-1次方來mod p,求一個(gè)與他們同余的數(shù)字。這就是k。
計(jì)算x,y時(shí)只需要考慮負(fù)數(shù)的問題,將負(fù)數(shù)加上p的倍數(shù)就可以轉(zhuǎn)換為一個(gè)正數(shù)來算出它取余p的值,這個(gè)負(fù)數(shù)的取余計(jì)算k也會(huì)用到。
對于計(jì)算階-p逆元計(jì)算以及np的加法放在后面說,這里主要說一下P+Q當(dāng)Q與P無任何聯(lián)系的時(shí)候,就直接用上面的公式計(jì)算。這個(gè)會(huì)單獨(dú)寫個(gè)函數(shù)addDif出來給后面加密用。還會(huì)單獨(dú)再寫一個(gè)函數(shù) everynp來給直接計(jì)算kC2,這是給后面解密用的,因?yàn)镃2是結(jié)構(gòu)體里沒有的,不能直接調(diào)用,思想是一樣的。計(jì)算階的也會(huì)分兩個(gè)函數(shù)寫,詳細(xì)的看3.2.5。
3.2.5 產(chǎn)生生成元和階
代碼會(huì)用到兩個(gè)結(jié)構(gòu)體,一個(gè)結(jié)構(gòu)體用來裝在有限域上的橢圓,里面的變量有他們的階,x,y,序號(hào),還有另外的一個(gè)結(jié)構(gòu)體數(shù)組,這是來裝這些點(diǎn)對應(yīng)的mP的坐標(biāo),這里的m從-1到階 沒有 0 ,這個(gè)數(shù)組的下標(biāo)就是m ,m為0 對應(yīng)-P,這樣將他的所有mP 保存起來,用于計(jì)算階,以及后面的加密需要用到mp 。
先生成一個(gè)有限域橢圓曲線方程式y(tǒng) 2 ≡ x 3 + a x + b ( m o d p ),a,b得是大于0的整數(shù),p需要是大素?cái)?shù)
計(jì)算生成元就是橢圓曲線在有限域上的點(diǎn)。將0到p之間的x代入y 2 ≡ x 3 + a x + b ( m o d p )來計(jì)算這里的,y是小于p的整數(shù),所以y的2次方是小于等于p-1的2次方的,這是一個(gè)限定條件,這樣來找與x 3 + a x + b 同余的數(shù)。
找到生成元后來找階,階的定義是如果橢圓曲線上一點(diǎn)P,存在最小的正整數(shù)n使得數(shù)乘n P = O ∞ ,則將n稱為P的階,根據(jù)P + ( ? P ) = O ∞ 就是找到mP=-P;P(x,y)的負(fù)元是 (x,-y mod p)= (x,p-y) ;若P的y的值為0則將它的階設(shè)置為1024,視為無限階,以及選擇私鑰也不能選擇這個(gè)點(diǎn),后面任意需要選點(diǎn)的情況都不能選擇這個(gè)點(diǎn)。階的話是要用到之前的1P,2P…mP的,因?yàn)?P=P+2P,需要兩個(gè)函數(shù),一個(gè)計(jì)算同點(diǎn)addsame和不同點(diǎn) addnp,當(dāng)點(diǎn)相同時(shí),則從結(jié)構(gòu)體調(diào)用m/2P的坐標(biāo)來計(jì)算,不同點(diǎn)則調(diào)用m/2P+m/2+1P來計(jì)算,把他們保存起來,調(diào)用函數(shù)找,直到找到m 可以滿足cP=-P 否則m為1024就不找了,視作無限階。根據(jù)P + ( ? P ) = O ∞推出這個(gè)點(diǎn)的階=m+1;
3.2.6選擇基點(diǎn)確定私鑰產(chǎn)生公鑰
選擇一個(gè)橢圓上的點(diǎn)作為基點(diǎn),然后選擇一個(gè)私鑰,私鑰k小于這個(gè)基點(diǎn)的階n,生成公開密鑰K=kG。這里選擇基點(diǎn)是靠輸入基點(diǎn)的序號(hào),根據(jù)序號(hào)找到基點(diǎn),在調(diào)取基點(diǎn)結(jié)構(gòu)體中的數(shù)組,找到下標(biāo)為k的數(shù)組,里面的坐標(biāo)就是kG,因?yàn)橛?jì)算了階,所以已經(jīng)有kG的值了。
4 相關(guān)算法及實(shí)現(xiàn)步驟
4.1坐標(biāo)結(jié)構(gòu)體和NP結(jié)構(gòu)體
struct add {int x;int y;//int jie; };struct pos {struct add np[1024];int x;int y;int num;int jie; int a; };4.2 有限域上的橢圓運(yùn)算算法
int calk(int x,int y)//計(jì)算k {int x1=x;int y1=y;int d=1;int t=0;int k=0;if(x1==0||y1==0)return 0;if(x1<0){x1=x1*(-1);t++;}if(y1<0){y1=y1*(-1);t++;}// printf("%d,%d\n",x1,y1);int i=1;int m,n;if(x1>y1){m=x1;n=y1;}else{m=y1;n=x1;}while((i=m%n)){m=n;n=i;}x1=x1/n;y1=y1/n;if(y1!=1){ for(d=0;;d++){if((d*y1)%p==1){break;}}}if(t%2!=0){ d=d*(-1);//符號(hào)不一樣}k=modsame(x1*d);//求同余return k; } struct pos fup(struct pos co1)//計(jì)算-p,保存-p,p到結(jié)構(gòu)體數(shù)組中 {struct pos co=co1;int i=0;co.np[0].x=co.x;co.np[0].y=p-co.y;co.np[1].x=co.x;co.np[1].y=co.y;return co; } struct pos addnp(struct pos co1,int jie)//計(jì)算相同兩個(gè)點(diǎn)的加法,不過是為算出階所寫的算法需要通過此算法得到前面的點(diǎn)才能算出后面的點(diǎn)5P=3P+2P得先調(diào)用后面addsame(p,2)再調(diào)用addnp(p,3),再add(p,5)這樣得到5P。 {struct pos co=co1;int i=0;int x1,y1,x2,y2;if(jie==1){return co;}x1=co.np[jie/2].x;y1=co.np[jie/2].y;x2=co.np[jie/2+1].x;y2=co.np[jie/2+1].y;int k=calk(y2-y1,x2-x1);co.np[jie].x=modsame(k*k-x1-x2);co.np[jie].y=modsame(k*(x1-co.np[jie].x)-y1);return co; }struct pos addsame(struct pos co1,int jie)//計(jì)算偶數(shù)個(gè)P的加法。是在之前P算出的基礎(chǔ)上計(jì)算的。 {struct pos co=co1;int i=0;int x,y;x=co.np[jie/2].x;y=co.np[jie/2].y;int k=calk(3*x*x+a,2*y);co.np[jie].x=modsame(k*k-2*x);co.np[jie].y=modsame(k*(x-co.np[jie].x)-y);return co; } struct pos everynp(struct pos c,int r)//任意一個(gè)點(diǎn)的r需要將前面的也算出來后才可以得到np。 {struct pos c2=c;int k=r;for(int j=2;j<=k;j++){if(j%2==0){c2=addsame(c2,j);}else{c2=addnp(c2,j);} }return c2; }struct pos addDif(struct pos co1,struct pos co2)//任意兩個(gè)點(diǎn)相加 {struct pos co=co1;struct pos co3=co2;int i=0;int x1,y1,x2,y2;x1=co.x;y1=co.y;x2=co3.x;y2=co3.y;int k=calk(y2-y1,x2-x1);co.x=modsame(k*k-x1-x2);co.y=modsame(k*(x1-co.x)-y1);return co; }4.3 功能模塊
4.3.1 產(chǎn)生生成元和階
效果圖
因?yàn)榫幋a到點(diǎn)是另外同學(xué)寫的就不把代碼傳上來了,編碼方式多種可以去網(wǎng)上搜索,接下來4,5,6,步算法設(shè)計(jì)
**第四步:**隨機(jī)生成一個(gè)r,r的值是小于你選擇的績點(diǎn)的階的。
**第五步:**計(jì)算C =M+rK,先調(diào)用公鑰K的結(jié)構(gòu)體里面的數(shù)組np 下標(biāo)為r 的x,y 這就是點(diǎn)rk 的坐標(biāo) ,然后再調(diào)用addDif(M,rK),計(jì)算C 2 = r G,調(diào)用基點(diǎn)G的結(jié)構(gòu)體里面的數(shù)組np的下標(biāo)為r的x,y就是G的坐標(biāo);
第六步: C 1? ?kC 2 先調(diào)用fup 函數(shù) 將-C2和C2本身的值存入C2結(jié)構(gòu)體的np數(shù)組里面,算出kC2 調(diào)用 everynp(C2,r)這里的r要從2到k循環(huán),因?yàn)橐猭C2是在算出C2,2C2,3C2…才能算出KC2再對KC2來求逆元調(diào)用fup函數(shù),再用任意兩個(gè)數(shù)addDif加法的函數(shù)來算出C1-KC2得到M
再對M解碼得到明文。
總結(jié)
我知道其實(shí)遞歸以及在每個(gè)函數(shù)的里面加上循環(huán)不用每次循環(huán)調(diào)用函數(shù)來達(dá)到計(jì)算前面的值,但我懶得改。以及遞歸不怎么寫,我隱隱覺得遞歸容易犯錯(cuò)。
總結(jié)
以上是生活随笔為你收集整理的ECC加密算法C简单实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue实现分页功能之最详细篇(一)
- 下一篇: asciidoc html java_如