(ECC)椭圆曲线加密算法原理和C++实现源码
目錄
(1)ECC加密原理:
(2)編譯生成LibTommath靜態(tài)庫(kù)
(3)ECC源碼
今天介紹一下利用LibTommath數(shù)學(xué)庫(kù)實(shí)現(xiàn)橢圓曲線加密算法的原理和源碼。
(1)ECC加密原理:
1、用戶A選定一條適合加密的橢圓曲線Ep(a,b)(如:y2=x3+ax+b),并取橢圓曲線上一點(diǎn),作為基點(diǎn)G。
2、用戶A選擇一個(gè)私有密鑰k,并生成公開密鑰K=kG。
3、用戶A將Ep(a,b)和點(diǎn)K,G傳給用戶B。
4、用戶B接到信息后 ,將待傳輸?shù)拿魑木幋a到Ep(a,b)上一點(diǎn)M,并產(chǎn)生一個(gè)隨機(jī)整數(shù)r(r<n)。
5、用戶B計(jì)算點(diǎn)C1=M+rK;C2=rG。
6、用戶B將C1、C2傳給用戶A。
7、用戶A接到信息后,計(jì)算C1-kC2,結(jié)果就是點(diǎn)M。因?yàn)?br /> ? ? ? ? ? C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M
再對(duì)點(diǎn)M進(jìn)行解碼就可以得到明文。
? 密碼學(xué)中,描述一條Fp上的橢圓曲線,常用到六個(gè)參量:?T=(p,a,b,G,n,h)。
(p 、a 、b 用來確定一條橢圓曲線,G為基點(diǎn),n為點(diǎn)G的階,h 是橢圓曲線上所有點(diǎn)的個(gè)數(shù)m與n相除的整數(shù)部分)
這幾個(gè)參量取值的選擇,直接影響了加密的安全性。參量值一般要求滿足以下幾個(gè)條件:
1、p 當(dāng)然越大越安全,但越大,計(jì)算速度會(huì)變慢,200位左右可以滿足一般安全要求;
2、p≠n×h;
3、pt≠1 (mod n),1≤t<20;
4、4a3+27b2≠0 (mod p);
5、n 為素?cái)?shù);
6、h≤4。
(2)編譯生成LibTommath靜態(tài)庫(kù)
經(jīng)評(píng)論區(qū)提醒,原LibTommath庫(kù)已經(jīng)刪除了,大家可以在Github上來下載:https://github.com/libtom/libtommath。
以下內(nèi)容可直接跳過:
首先下載LibTommath的源碼,網(wǎng)址為:Best Open Source Mac Libraries Software 2022
下載后,解壓如圖所示:
打開bn.pdf文件后,這是該庫(kù)的使用手冊(cè),在第10頁(yè)會(huì)看到如下指令,在終端執(zhí)行make命令即可生成靜態(tài)庫(kù):libtommath.a。
附:在執(zhí)行編譯時(shí)可能會(huì)生成一些小問題,那就是需要把tommath.h和tommath_superclass.h需要錢修改一下,如下:
只是頭文件包含的問題,視具體情況來修改。
(3)ECC源碼
下面是ECC源碼。
/* 1、用戶A選定一條適合加密的橢圓曲線Ep(a,b)(如:y2=x3+ax+b),并取橢圓曲線上一點(diǎn),作為基點(diǎn)G。2、用戶A選擇一個(gè)私有密鑰k,并生成公開密鑰K=kG。3、用戶A將Ep(a,b)和點(diǎn)K,G傳給用戶B。4、用戶B接到信息后 ,將待傳輸?shù)拿魑木幋a到Ep(a,b)上一點(diǎn)M,并產(chǎn)生一個(gè)隨機(jī)整數(shù)r(r<n)。5、用戶B計(jì)算點(diǎn)C1=M+rK;C2=rG。6、用戶B將C1、C2傳給用戶A。7、用戶A接到信息后,計(jì)算C1-kC2,結(jié)果就是點(diǎn)M。因?yàn)镃1-kC2=M+rK-k(rG)=M+rK-r(kG)=M再對(duì)點(diǎn)M進(jìn)行解碼就可以得到明文。密碼學(xué)中,描述一條Fp上的橢圓曲線,常用到六個(gè)參量:T=(p,a,b,G,n,h)。(p 、a 、b 用來確定一條橢圓曲線,G為基點(diǎn),n為點(diǎn)G的階,h 是橢圓曲線上所有點(diǎn)的個(gè)數(shù)m與n相除的整數(shù)部分)這幾個(gè)參量取值的選擇,直接影響了加密的安全性。參量值一般要求滿足以下幾個(gè)條件:1、p 當(dāng)然越大越安全,但越大,計(jì)算速度會(huì)變慢,200位左右可以滿足一般安全要求;2、p≠n×h;3、pt≠1 (mod n),1≤t<20;4、4a3+27b2≠0 (mod p);5、n 為素?cái)?shù);6、h≤4。 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include "tommath.h" #include <time.h>#define BIT_LEN 800 #define KEY_LONG 128 //私鑰比特長(zhǎng) #define P_LONG 200 //有限域P比特長(zhǎng) #define EN_LONG 40 //一次取明文字節(jié)數(shù)(x,20)(y,20)//得到lon比特長(zhǎng)素?cái)?shù) int GetPrime(mp_int *m,int lon); //得到B和G點(diǎn)X坐標(biāo)G點(diǎn)Y坐標(biāo) void Get_B_X_Y(mp_int *x1,mp_int *y1,mp_int *b, mp_int *a, mp_int *p); //點(diǎn)乘 bool Ecc_points_mul(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int *d,mp_int *a,mp_int *p); //點(diǎn)加 int Two_points_add(mp_int *x1,mp_int *y1,mp_int *x2,mp_int *y2,mp_int *x3,mp_int *y3,mp_int *a,bool zero,mp_int *p); //二進(jìn)制存儲(chǔ)密文 int chmistore(mp_int *a,FILE *fp); //把讀取的字符存入mp_int型數(shù) int putin(mp_int *a,char *ch,int chlong); //ECC加密 void Ecc_encipher(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int *a,mp_int *p); //ECC解密 void Ecc_decipher(mp_int *k, mp_int *a,mp_int *p); //實(shí)現(xiàn)將mp_int數(shù)a中的比特串還原為字符串并賦給字符串ch: int chdraw(mp_int *a,char *ch); //取密文 int miwendraw(mp_int *a,char *ch,int chlong);int myrng(unsigned char *dst, int len, void *dat) {int x;for (x = 0; x < len; x++) dst[x] = rand() & 0xFF;return len; }using namespace std; int main(){cout<<"\n 本程序?qū)崿F(xiàn)橢圓曲線的加密解密"<<endl;cout<<"\n------------------------------------------------------------------------\n"<<endl;mp_int GX;mp_int GY;mp_int K;//私有密鑰mp_int A;mp_int B;mp_int QX;mp_int QY;mp_int P;//Fp中的p(有限域P)mp_init(&GX);mp_init(&GY);mp_init(&K);mp_init(&A);mp_init(&B);mp_init(&QX);mp_init(&QY);mp_init(&P);time_t t; srand( (unsigned) time( &t ) );printf("橢圓曲線的參數(shù)如下(以十進(jìn)制顯示):\n"); GetPrime(&P,P_LONG);printf("有限域 P 是:\n"); char temp[800]={0};mp_toradix(&P,temp,10);printf("%s\n",temp); GetPrime(&A,30);char tempA[800]={0};printf("曲線參數(shù) A 是:\n"); mp_toradix(&A,tempA,10);printf("%s\n",tempA); Get_B_X_Y(&GX,&GY,&B,&A,&P);char tempB[800]={0};printf("曲線參數(shù) B 是:\n"); mp_toradix(&B,tempB,10);printf("%s\n",tempB); char tempGX[800]={0};printf("曲線G點(diǎn)X坐標(biāo)是:\n"); mp_toradix(&GX,tempGX,10);printf("%s\n",tempGX); char tempGY[800]={0};printf("曲線G點(diǎn)Y坐標(biāo)是:\n");mp_toradix(&GY,tempGY,10);printf("%s\n",tempGY); //------------------------------------------------------------------GetPrime(&K,KEY_LONG);char tempK[800]={0};printf("私鑰 K 是:\n");mp_toradix(&K,tempK,10);printf("%s\n",tempK); Ecc_points_mul(&QX,&QY,&GX,&GY,&K,&A,&P);char tempQX[800]={0};printf("公鑰X坐標(biāo)是:\n");mp_toradix(&QX,tempQX,10);printf("%s\n",tempQX); char tempQY[800]={0};printf("公鑰Y坐標(biāo)是:\n");mp_toradix(&QY,tempQY,10);printf("%s\n",tempQY); printf("\n------------------------------------------------------------------------\n");Ecc_encipher(&QX,&QY,&GX,&GY,&A,&P);//加密printf("\n------------------------------------------------------------------------\n");Ecc_decipher(&K,&A,&P);//解密printf("\n------------------------------------------------------------------------\n");char cc;cout<<"\n\n請(qǐng)擊一鍵退出!\n";cin>>cc;mp_clear(&GX);mp_clear(&GY);mp_clear(&K);//私有密鑰mp_clear(&A);mp_clear(&B);mp_clear(&QX);mp_clear(&QY);mp_clear(&P);//Fp中的p(有限域P)return 0; }int GetPrime(mp_int *m,int lon){mp_prime_random_ex(m, 10, lon, (rand()&1)?LTM_PRIME_2MSB_OFF:LTM_PRIME_2MSB_ON, myrng, NULL);return MP_OKAY; }void Get_B_X_Y(mp_int *x1,mp_int *y1,mp_int *b, mp_int *a, mp_int *p) {mp_int tempx,tempy;mp_int temp;mp_int compare;mp_int temp1;mp_int temp2;mp_int temp3;mp_int temp4;mp_int temp5;mp_int temp6;mp_int temp7;mp_int temp8;mp_init_set_int (&compare, 0);mp_init(&tempx);mp_init(&tempy);mp_init(&temp);mp_init(&temp1);mp_init(&temp2);mp_init(&temp3);mp_init(&temp4);mp_init(&temp5);mp_init(&temp6);mp_init(&temp7);mp_init(&temp8);while(1){//4a3+27b2≠0 (mod p)GetPrime(b,40);mp_expt_d(a, 3, &temp1);mp_sqr(b, &temp2);mp_mul_d(&temp1, 4, &temp3);mp_mul_d(&temp2, 27, &temp4);mp_add(&temp3, &temp4, &temp5);mp_mod(&temp5,p,&temp);if(mp_cmp(&temp, &compare)!=0 ){break;}}//y2=x3+ax+b,隨機(jī)產(chǎn)生X坐標(biāo),根據(jù)X坐標(biāo)計(jì)算Y坐標(biāo)GetPrime(x1,30);mp_expt_d(x1, 3, &temp6);mp_mul(a, x1, &temp7);mp_add(&temp6, &temp7, &temp8);mp_add(&temp8, b, &tempx);mp_sqrt(&tempx, y1);mp_clear(&tempx);mp_clear(&tempy);mp_clear(&temp);mp_clear(&temp1);mp_clear(&temp2);mp_clear(&temp3);mp_clear(&temp4);mp_clear(&temp5);mp_clear(&temp6);mp_clear(&temp7);mp_clear(&temp8);}bool Ecc_points_mul(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int *d,mp_int *a,mp_int *p) { mp_int X1, Y1; mp_int X2, Y2; mp_int X3, Y3; mp_int XX1, YY1; mp_int A,P;int i; bool zero=false; char Bt_array[800]={0}; char cm='1';mp_toradix(d,Bt_array,2); mp_init_set_int(&X3, 0);mp_init_set_int(&Y3, 0);mp_init_copy(&X1, px);mp_init_copy(&X2, px);mp_init_copy(&XX1, px);mp_init_copy(&Y1, py);mp_init_copy(&Y2, py);mp_init_copy(&YY1, py);mp_init_copy(&A, a);mp_init_copy(&P, p);for(i=1;i<=KEY_LONG-1;i++){mp_copy(&X2, &X1);mp_copy(&Y2, &Y1);Two_points_add(&X1,&Y1,&X2,&Y2,&X3,&Y3,&A,zero,&P); mp_copy(&X3, &X2);mp_copy(&Y3, &Y2);if(Bt_array[i]==cm){mp_copy(&XX1, &X1);mp_copy(&YY1, &Y1);Two_points_add(&X1,&Y1,&X2,&Y2,&X3,&Y3,&A,zero,&P);mp_copy(&X3, &X2);mp_copy(&Y3, &Y2);}}if(zero){cout<<"It is Zero_Unit!";return false;//如果Q為零從新產(chǎn)生D}mp_copy(&X3, qx);mp_copy(&Y3, qy);mp_clear(&X1);mp_clear(&Y1);mp_clear(&X2);mp_clear(&Y2);mp_clear(&X3);mp_clear(&Y3);mp_clear(&XX1);mp_clear(&YY1);mp_clear(&A);mp_clear(&P);return true; }//兩點(diǎn)加 int Two_points_add(mp_int *x1,mp_int *y1,mp_int *x2,mp_int *y2,mp_int *x3,mp_int *y3,mp_int *a,bool zero,mp_int *p) { mp_int x2x1; mp_int y2y1; mp_int tempk; mp_int tempy; mp_int tempzero; mp_int k; mp_int temp1; mp_int temp2; mp_int temp3; mp_int temp4; mp_int temp5; mp_int temp6; mp_int temp7; mp_int temp8; mp_int temp9; mp_int temp10;mp_init(&x2x1); mp_init(&y2y1); mp_init(&tempk); mp_init(&tempy); mp_init(&tempzero); mp_init(&k); mp_init(&temp1); mp_init(&temp2); mp_init_set(&temp3,2); mp_init(&temp4); mp_init(&temp5); mp_init(&temp6); mp_init(&temp7); mp_init(&temp8); mp_init(&temp9); mp_init(&temp10);if(zero){mp_copy(x1, x3);mp_copy(y1, y3);zero=false;goto L;}mp_zero(&tempzero);mp_sub(x2, x1, &x2x1);if(mp_cmp(&x2x1,&tempzero)==-1){mp_add(&x2x1, p, &temp1);mp_zero(&x2x1);mp_copy(&temp1, &x2x1);}mp_sub(y2, y1, &y2y1);if(mp_cmp(&y2y1,&tempzero)==-1){mp_add(&y2y1, p, &temp2);mp_zero(&y2y1);mp_copy(&temp2, &y2y1);}if(mp_cmp(&x2x1, &tempzero)!=0){mp_invmod(&x2x1,p,&tempk);mp_mulmod(&y2y1, &tempk, p, &k);}else{if(mp_cmp(&y2y1, &tempzero)==0){mp_mulmod(&temp3,y1,p,&tempy);mp_invmod(&tempy,p,&tempk);mp_sqr(x1, &temp4); mp_mul_d(&temp4, 3, &temp5);mp_add(&temp5, a, &temp6);mp_mulmod(&temp6, &tempk, p, &k);}else{zero=true;goto L;}} mp_sqr(&k, &temp7);mp_sub(&temp7, x1, &temp8);mp_submod(&temp8, x2, p, x3);mp_sub(x1, x3, &temp9);mp_mul(&temp9, &k, &temp10);mp_submod(&temp10, y1, p, y3);L:mp_clear(&x2x1);mp_clear(&y2y1);mp_clear(&tempk);mp_clear(&tempy);mp_clear(&tempzero);mp_clear(&k);mp_clear(&temp1);mp_clear(&temp2);mp_clear(&temp3);mp_clear(&temp4);mp_clear(&temp5);mp_clear(&temp6);mp_clear(&temp7);mp_clear(&temp8);mp_clear(&temp9);mp_clear(&temp10);return 1;}//二進(jìn)制存儲(chǔ)密文 int chmistore(mp_int *a,FILE *fp) {int i,j;char ch;char chtem[4];mp_digit yy=(mp_digit)255;for (i=0; i <= a->used - 1; i++) { chtem[3]=(char)(a->dp[i] & yy); chtem[2]=(char)((a->dp[i] >> (mp_digit)8) & yy); chtem[1]=(char)((a->dp[i] >> (mp_digit)16) & yy); chtem[0]=(char)((a->dp[i] >> (mp_digit)24) & yy);for(j=0;j<4;j++){fprintf(fp,"%c",chtem[j]);}} ch=char(255);fprintf(fp, "%c", ch);return MP_OKAY; }//把讀取的字符存入mp_int型數(shù) int putin(mp_int *a,char *ch,int chlong) {mp_digit *temp,yy;int i,j,res;if(a->alloc<chlong*2/7+2){if((res=mp_grow(a,chlong*2/7+2))!=MP_OKAY)return res;}a->sign=0;mp_zero(a);temp=a->dp;i=0;yy=(mp_digit)15;if(chlong<4){for(j=chlong-1;j>=0;j--){*temp |= (mp_digit)(ch[j] & 255);*temp <<= (mp_digit)CHAR_BIT;}*temp >>= (mp_digit)8;a->used=1;return MP_OKAY;}if(chlong<7){i+=4;*++temp |= (mp_digit)(ch[i-1] & yy);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-2] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-3] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp-- |= (mp_digit)(ch[i-4] & 255); //存放被切分的字符的低四位for(j=chlong-1;j>=i;j--){ *temp |= (mp_digit)(ch[j] & 255);*temp <<= (mp_digit)CHAR_BIT; }*temp >>= (mp_digit)4;*temp |= (mp_digit)((ch[i-1] & 255) >> 4); //存放被切分的字符的高四位a->used=2;return MP_OKAY;}//以7個(gè)字符為單元循環(huán),把七個(gè)字符放入的mp_int 的兩個(gè)單元中for(j=0;j<chlong/7;j++){i+=7;*++temp |= (mp_digit)(ch[i-1] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-2] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-3] & 255);*temp <<= (mp_digit)4;*temp-- |= (mp_digit)((ch[i-4] & 255) >> 4); //存放被切分的字符的高四位*temp |= (mp_digit)(ch[i-4] & yy); //存放被切分的字符的低四位*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-5] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-6] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp++ |= (mp_digit)(ch[i-7] & 255); temp++;}if((chlong>=7)&&(chlong%7!=0)) //剩余字符的存放{if(chlong%7 < 4) //剩余字符少余4個(gè)時(shí),只需一個(gè)mp_digit單元存放{for(j=chlong-1;j>=i;j--){*temp |= (mp_digit)(ch[j] & 255);*temp <<= (mp_digit)CHAR_BIT;}*temp >>= (mp_digit)8;a->used=chlong*2/7+1;}else{ //剩余字符不小于4個(gè)時(shí),需兩個(gè)mp_digit單元存放i+=4;*temp |= (mp_digit)(ch[i-1] & yy);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-2] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-3] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp++ |= (mp_digit)(ch[i-4] & 255); //存放被切分的字符的低四位for(j=chlong-1;j>=i;j--){ *temp |= (mp_digit)(ch[j] & 255);*temp <<= (mp_digit)CHAR_BIT; }*temp >>= (mp_digit)4;*temp |= (mp_digit)((ch[i-1] & 255) >> 4); //存放被切分的字符的高四位a->used=chlong*2/7+2;}}else{a->used=chlong*2/7;}return MP_OKAY; }void Ecc_encipher(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int *a,mp_int *p){ //公鑰X、Y坐標(biāo),曲線G點(diǎn)X、Y坐標(biāo),曲線參數(shù)A,有限域Pmp_int mx, my;mp_int c1x, c1y;mp_int c2x, c2y;mp_int r;mp_int tempx, tempy;bool zero=false;FILE *fp,*fq;int i;char miwenx[280]={0};char miweny[280]={0};char stemp[650]={0};mp_init(&mx);mp_init(&my);mp_init(&c1x);mp_init(&c1y);mp_init(&c2x);mp_init(&c2y);mp_init(&r);mp_init(&tempx);mp_init(&tempy);GetPrime(&r, 100);char filehead[60],filefoot[20],filename[85]={0};cout<<"請(qǐng)輸入您要加密文件的存放路徑和文件名(如: c:\\000\\大整數(shù)運(yùn)算 ):"<<endl;cin>>filehead;cout<<"請(qǐng)輸入您要加密文件的擴(kuò)展名(如: .doc ):"<<endl;cin>>filefoot;strcpy(filename,filehead);strcat(filename,filefoot);//打開要加密文件if((fp=fopen(filename,"rb"))==NULL){printf("can not open the file!");exit(1);}unsigned int FileLong=0;//文件字符長(zhǎng)度char ChTem;//臨時(shí)字符變int Frequency=0;int Residue=0;while( !feof(fp) )//找文件字符長(zhǎng)度{ChTem = fgetc( fp );FileLong++;}--FileLong;Frequency = FileLong/EN_LONG;Residue = FileLong%EN_LONG;printf("Frequency= %d, Residue= %d\n", Frequency, Residue);int enlongtemp=EN_LONG/2;//printf("%d\n",Frequency); //printf("%d\n",Residue); char filemi[85];strcpy(filemi,filehead);strcat(filemi,"密文");strcat(filemi,filefoot);//打開保存密文文件if((fq=fopen(filemi,"wb"))==NULL){printf("can not open the file!\n");exit(1);}printf("\n開始加密...\n");rewind(fp);clock_t start, finish;double duration;for(i=0; i<Frequency; i++){ fread(miwenx,1,enlongtemp,fp);//讀入字符串miwenx[enlongtemp]=char(255);fread(miweny,1,enlongtemp,fp);//讀入字符串miweny[enlongtemp]=char(255);putin(&mx, miwenx,enlongtemp+1);//文件存入 putin(&my, miweny,enlongtemp+1);//文件存入Ecc_points_mul(&c2x,&c2y,px,py,&r,a,p);//加密Ecc_points_mul(&tempx,&tempy,qx,qy,&r,a,p); Two_points_add(&mx,&my,&tempx,&tempy,&c1x,&c1y,a,zero,p);//保存密文 chmistore(&c1x,fq); chmistore(&c1y,fq);chmistore(&c2x,fq);chmistore(&c2y,fq);}//剩余字符處理if ( Residue > 0){if (Residue <= enlongtemp ) {fread(miwenx,1,Residue,fp);//讀入字符串miwenx[Residue]=char(255);putin(&mx, miwenx,Residue+1);//文件存入 mp_zero(&my);}else{fread(miwenx,1,enlongtemp,fp);//讀入字符串miwenx[enlongtemp]=char(255);fread(miweny,1,Residue-enlongtemp,fp);//讀入字符串miweny[Residue-enlongtemp]=char(255);putin(&mx, miwenx,enlongtemp+1);//文件存入 putin(&my, miweny,Residue-enlongtemp+1);//文件存入 }Ecc_points_mul(&c2x,&c2y,px,py,&r,a,p);//加密Ecc_points_mul(&tempx,&tempy,qx,qy,&r,a,p); Two_points_add(&mx,&my,&tempx,&tempy,&c1x,&c1y,a,zero,p);//保存密文 chmistore(&c1x,fq); chmistore(&c1y,fq);chmistore(&c2x,fq);chmistore(&c2y,fq); }cout<<"\nok!加密完畢!"<<endl;cout<<"密文以二進(jìn)制保存"<<endl;cout<<"密文存放路徑為 "<<filemi<<endl ;fclose(fq);fclose(fp);mp_clear(&mx);mp_clear(&my);mp_clear(&c1x);mp_clear(&c1y);mp_clear(&c2x);mp_clear(&c2y);mp_clear(&r);mp_clear(&tempx);mp_clear(&tempy);}//取密文int miwendraw(mp_int *a,char *ch,int chlong) {mp_digit *temp;int i,j,res;if(a->alloc<chlong/4){if((res=mp_grow(a,chlong/4))!=MP_OKAY)return res;}a->alloc=chlong/4;a->sign=0;mp_zero(a);temp=a->dp;i=0;for(j=0;j<chlong/4;j++){i+=4;*temp |= (mp_digit)(ch[i-4] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-3] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp |= (mp_digit)(ch[i-2] & 255);*temp <<= (mp_digit)CHAR_BIT;*temp++ |= (mp_digit)(ch[i-1] & 255); }a->used=chlong/4;return MP_OKAY; }//實(shí)現(xiàn)將mp_int數(shù)a中的比特串還原為字符串并賦給字符串ch: int chdraw(mp_int *a,char *ch) {int i,j;mp_digit *temp,xx,yy;temp=a->dp;i=0;yy=(mp_digit)255; //用于位與運(yùn)算,取八位比特串xx=(mp_digit)15; //用于位與運(yùn)算,取四位比特串for(j=0;j<a->used/2;j++) //以兩個(gè)單元為循環(huán),把兩個(gè)單元的比特串賦給7個(gè)字符{i+=7;ch[i-4]=(char)(*++temp & xx);ch[i-3]=(char)((*temp >> (mp_digit)4) & yy); ch[i-2]=(char)((*temp >> (mp_digit)12) & yy);ch[i-1]=(char)((*temp-- >> (mp_digit)20) & yy);ch[i-7]=(char)(*temp & yy);ch[i-6]=(char)((*temp >> (mp_digit)8) & yy);ch[i-5]=(char)((*temp >> (mp_digit)16) & yy);ch[i-4] <<= 4;ch[i-4]+=(char)((*temp++ >> (mp_digit)24) & xx);temp++;}if(a->used%2!=0) //剩于一個(gè)單元的處理{ch[i++] = (char)(*temp & yy);ch[i++] = (char)((*temp >> (mp_digit)8) & yy);ch[i++] = (char)((*temp >> (mp_digit)16) & yy);}--i;while(int(ch[i]&0xFF) != 255 && i>0) i--;return i;}void Ecc_decipher(mp_int *k, mp_int *a,mp_int *p){mp_int c1x, c1y;mp_int c2x, c2y;mp_int tempx, tempy;mp_int mx, my;mp_int temp;mp_init(&temp);mp_init(&c1x);mp_init(&c1y);mp_init(&c2x);mp_init(&c2y);mp_init(&tempx);mp_init(&tempy);mp_init(&mx);mp_init(&my);mp_int tempzero;mp_init(&tempzero);int i;char stemp[700]={0};FILE *fp,*fq;bool zero=false;clock_t start, finish;double duration;char filehead[60],filefoot[20],filename[85]={0};cout<<"請(qǐng)輸入您要解密的文件的存放路徑和文件名(如: c:\\000\\大整數(shù)運(yùn)算 ):"<<endl;cin>>filehead;cout<<"請(qǐng)輸入您要解密的文件的擴(kuò)展名(如: .doc ):"<<endl;cin>>filefoot;strcpy(filename,filehead);strcat(filename,filefoot);printf("\n開始解密\n");if((fp=fopen(filename,"rb"))==NULL){printf("can not open the file!");exit(1);}//打開保存解密結(jié)果文件char filemi[80];strcpy(filemi, filehead);strcat(filemi, "解密");strcat(filemi, filefoot);if((fq=fopen(filemi,"wb"))==NULL){printf("can not open the file!");exit(1);}rewind(fp);while(!feof(fp)){i=0;while(1){stemp[i]=fgetc(fp);if(i%4==0){if(int(stemp[i]&0xFF) == 255 ) goto L1;}i++;}L1: miwendraw(&c1x, stemp, i);i=0;while(1){stemp[i]=fgetc(fp);if(i%4==0){if(int(stemp[i]&0xFF) == 255 ) goto L2;}i++;}L2: miwendraw(&c1y, stemp, i);i=0;while(1){stemp[i]=fgetc(fp);if(i%4==0){if(int(stemp[i]&0xFF) == 255 ) goto L3;}i++;}L3: miwendraw(&c2x, stemp, i);i=0;while(1){stemp[i]=fgetc(fp);if(i%4==0){if(int(stemp[i]&0xFF) == 255 ) goto L4;}i++;}L4: miwendraw(&c2y, stemp, i);mp_zero(&tempzero);if(mp_cmp(&c1x, &tempzero)==0) break;Ecc_points_mul(&tempx, &tempy, &c2x, &c2y, k, a, p); mp_neg(&tempy, &temp);Two_points_add(&c1x,&c1y,&tempx,&temp,&mx,&my,a,zero,p);int chtem;chtem=chdraw(&mx,stemp);//從ming中取出字符串//保存解密結(jié)果for(int kk=0;kk<chtem;kk++){fprintf(fq,"%c",stemp[kk]);}chtem=chdraw(&my,stemp);//從ming中取出字符串//保存解密結(jié)果for(int kk=0;kk<chtem;kk++){fprintf(fq,"%c",stemp[kk]);}}cout<<"\nok!解密完畢!"<<endl;cout<<"解密后的文字存放路徑為 "<<filemi<<endl;fclose(fq);fclose(fp);mp_clear(&c1x);mp_clear(&c1y);mp_clear(&c2x);mp_clear(&c2y);mp_clear(&tempx);mp_clear(&tempy);mp_clear(&mx);mp_clear(&my);mp_clear(&temp);}在命令行執(zhí)行:
$ g++ ecc.cpp -o main libtommath.a生成可執(zhí)行文件main。
總結(jié)
以上是生活随笔為你收集整理的(ECC)椭圆曲线加密算法原理和C++实现源码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mseq matlab,Matlab生成
- 下一篇: McEPOC.exe是什么进程 有何作用