(ECC)椭圆曲线加密算法原理和C++实现源码

目录

(1)ECC加密原理:

(2)编译生成LibTommath静态库

(3)ECC源码


今天介绍一下利用LibTommath数学库实现椭圆曲线加密算法的原理和源码。

(1)ECC加密原理:

 1、用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G。
 2、用户A选择一个私有密钥k,并生成公开密钥K=kG。
 3、用户A将Ep(a,b)和点K,G传给用户B。
 4、用户B接到信息后 ,将待传输的明文编码到Ep(a,b)上一点M,并产生一个随机整数r(r<n)。
 5、用户B计算点C1=M+rK;C2=rG。
 6、用户B将C1、C2传给用户A。
 7、用户A接到信息后,计算C1-kC2,结果就是点M。因为
          C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M
   再对点M进行解码就可以得到明文。

  密码学中,描述一条Fp上的椭圆曲线,常用到六个参量: T=(p,a,b,G,n,h)。
  (p 、a 、b 用来确定一条椭圆曲线,G为基点,n为点G的阶,h 是椭圆曲线上所有点的个数m与n相除的整数部分)

  这几个参量取值的选择,直接影响了加密的安全性。参量值一般要求满足以下几个条件:

  1、p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求;
  2、p≠n×h;
  3、pt≠1 (mod n),1≤t<20;
  4、4a3+27b2≠0 (mod p);
  5、n 为素数;
  6、h≤4。

(2)编译生成LibTommath静态库

经评论区提醒,原LibTommath库已经删除了,大家可以在Github上来下载:https://github.com/libtom/libtommath。


以下内容可直接跳过:

首先下载LibTommath的源码,网址为:Best Open Source Mac Libraries Software 2022

下载后,解压如图所示:

打开bn.pdf文件后,这是该库的使用手册,在第10页会看到如下指令,在终端执行make命令即可生成静态库:libtommath.a

附:在执行编译时可能会生成一些小问题,那就是需要把tommath.h和tommath_superclass.h需要钱修改一下,如下:

只是头文件包含的问题,视具体情况来修改。

(3)ECC源码

下面是ECC源码。

/* 1、用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G。2、用户A选择一个私有密钥k,并生成公开密钥K=kG。3、用户A将Ep(a,b)和点K,G传给用户B。4、用户B接到信息后 ,将待传输的明文编码到Ep(a,b)上一点M,并产生一个随机整数r(r<n)。5、用户B计算点C1=M+rK;C2=rG。6、用户B将C1、C2传给用户A。7、用户A接到信息后,计算C1-kC2,结果就是点M。因为C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M再对点M进行解码就可以得到明文。密码学中,描述一条Fp上的椭圆曲线,常用到六个参量:T=(p,a,b,G,n,h)。(p 、a 、b 用来确定一条椭圆曲线,G为基点,n为点G的阶,h 是椭圆曲线上所有点的个数m与n相除的整数部分)这几个参量取值的选择,直接影响了加密的安全性。参量值一般要求满足以下几个条件:1、p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求;2、p≠n×h;3、pt≠1 (mod n),1≤t<20;4、4a3+27b2≠0 (mod p);5、n 为素数;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  //私钥比特长
#define P_LONG 200    //有限域P比特长
#define EN_LONG 40    //一次取明文字节数(x,20)(y,20)//得到lon比特长素数
int GetPrime(mp_int *m,int lon);
//得到B和G点X坐标G点Y坐标
void Get_B_X_Y(mp_int *x1,mp_int *y1,mp_int *b,  mp_int *a,  mp_int *p);
//点乘
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);
//点加
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);
//二进制存储密文
int chmistore(mp_int *a,FILE *fp);
//把读取的字符存入mp_int型数
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);
//实现将mp_int数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          本程序实现椭圆曲线的加密解密"<<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("椭圆曲线的参数如下(以十进制显示):\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("曲线参数 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("曲线参数 B 是:\n");    mp_toradix(&B,tempB,10);printf("%s\n",tempB); char tempGX[800]={0};printf("曲线G点X坐标是:\n");    mp_toradix(&GX,tempGX,10);printf("%s\n",tempGX);   char tempGY[800]={0};printf("曲线G点Y坐标是:\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坐标是:\n");mp_toradix(&QX,tempQX,10);printf("%s\n",tempQX); char tempQY[800]={0};printf("公钥Y坐标是:\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请击一键退出!\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,随机产生X坐标,根据X坐标计算Y坐标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为零从新产生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;
}//两点加
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;}//二进制存储密文
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型数
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个字符为单元循环,把七个字符放入的mp_int 的两个单元中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个时,只需一个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个时,需两个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坐标,曲线G点X、Y坐标,曲线参数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<<"请输入您要加密文件的存放路径和文件名(如:  c:\\000\\大整数运算  ):"<<endl;cin>>filehead;cout<<"请输入您要加密文件的扩展名(如:  .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;//文件字符长度char ChTem;//临时字符变int Frequency=0;int Residue=0;while( !feof(fp) )//找文件字符长度{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<<"密文以二进制保存"<<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;
}//实现将mp_int数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;  //用于位与运算,取八位比特串xx=(mp_digit)15;  //用于位与运算,取四位比特串for(j=0;j<a->used/2;j++)  //以两个单元为循环,把两个单元的比特串赋给7个字符{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)  //剩于一个单元的处理{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<<"请输入您要解密的文件的存放路径和文件名(如:  c:\\000\\大整数运算  ):"<<endl;cin>>filehead;cout<<"请输入您要解密的文件的扩展名(如:  .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);}//打开保存解密结果文件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中取出字符串//保存解密结果for(int kk=0;kk<chtem;kk++){fprintf(fq,"%c",stemp[kk]);}chtem=chdraw(&my,stemp);//从ming中取出字符串//保存解密结果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);}

在命令行执行:

$ g++ ecc.cpp -o main libtommath.a

生成可执行文件main。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/440153.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【POJ - 2553】The Bottom of a Graph(tarjan强连通分量缩点,模板题)

题干&#xff1a; We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called vertices (or nodes). Let E be a subset of the Cartesian product VV, its elements being called edges. Then G(…

c语言3种链接属性: 外部(external), 内部(internal),无设置(none)

c语言中&#xff0c;多个文件组合的时候&#xff0c;有可能标示名相同&#xff0c;那么这个时候编译器如何判别的呢&#xff1f; c语言中有3种链接属性: 外部&#xff08;external&#xff1a;可以被其他文件访问到&#xff09;, 内部(internal&#xff1a;无法被其他文件访问到…

java 数组习题

2.写一个函数&#xff0c;返回一个整数数组的平均值 package com.fxm.day05.test; public class Day05test{public static void main(String[] args){int[] a1 {2,9,5,7,4};int n average(a1);System.out.println(n);}public static int average(int[] a){int sum 0;for(in…

机器学习笔记(1):Introduction

目录 1&#xff09;welcome 2&#xff09;What is Machine Learning 3&#xff09;Supervised Learning 4&#xff09;Unsupervised Learning 1&#xff09;welcome 第一个视频主要介绍了机器学习目前的案例&#xff0c;主要有&#xff1a;数据库挖掘、医疗记录、生物工程…

【POJ - 3352】Road Construction(Tarjan,边双连通分量)

题干&#xff1a; Its almost summer time, and that means that its almost summer construction time! This year, the good people who are in charge of the roads on the tropical island paradise of Remote Island would like to repair and upgrade the various roads…

C++匿名命名空间

当定义一个命名空间时&#xff0c;可以忽略这个命名空间的名称&#xff1a; namespce {char c;int i;double d;}编译器在内部会为这个命名空间生成一个唯一的名字&#xff0c;而且还会为这个匿名的命名空间生成一条using指令。所以上面的代码在效果上等同于&#xff1a;namespa…

机器学习简易入门-附推荐学习资料

目录 &#xff08;1&#xff09;机器学习正规学习路线 &#xff08;2&#xff09;机器学习快速入门 &#xff08;3&#xff09;总结 感谢黄海广博士的分享 原创&#xff1a; 机器学习初学者 机器学习初学者 今天 机器学习如何入门&#xff1f;目前没有明确的答案。本站面向…

python 习题

使用蒙特-卡罗方法计算圆周率近似值 蒙特-卡罗方法是一种通过概率来得到问题近似解的方法。假设又一块边长为2的正方形木板&#xff0c;上面画一个单位圆&#xff0c;然后随意往木板上扔飞镖&#xff0c;落点坐标(x,y)必然在木板上(更多的是落在单位圆内)&#xff0c;如果扔的…

C++11中的std::function

原文地址&#xff1a;http://www.jellythink.com/archives/771 看看这段代码 先来看看下面这两行代码&#xff1a; std::function<void(EventKeyboard::KeyCode, Event*)> onKeyPressed; std::function<void(EventKeyboard::KeyCode, Event*)> onKeyReleased; 这两…

【HDU - 3394】Railway(点双连通分量,Tarjan算法,思维tricks)

题干&#xff1a; There are some locations in a park, and some of them are connected by roads. The park manger needs to build some railways along the roads, and he would like to arrange tourist routes to each circuit. If a railway belongs to more than one …

飞机大战(简易版)

一、游戏分析 飞机大战中的主要“角色”有&#xff1a; 1.英雄 2.敌方飞机 3.英雄发射的子弹 我们需要控制的有&#xff1a; 1.绘制屏幕内的角色 2.控制角色的逻辑&#xff0c;比如&#xff1a;敌方飞机与我方飞机的碰撞检测&#xff0c;我方飞机发射的子弹与敌方飞机之间的碰撞…

在Ubuntu上安装Keras深度学习框架

目录 1&#xff09;安装pip 2&#xff09;安装Python科学套件 3&#xff09;安装TensorFlow 4&#xff09;安装keras 5&#xff09;安装Jupyter Notebook 6&#xff09;运行Keras 本文介绍如何在Ubuntu上安装Keras深度学习框架。 1&#xff09;安装pip 安装pip包&#…

【POJ - 1523】SPF(Tarjan求割点,求分割成的连通块数,模板题,tricks)

题干&#xff1a; Consider the two networks shown below. Assuming that data moves around these networks only between directly connected nodes on a peer-to-peer basis, a failure of a single node, 3, in the network on the left would prevent some of the still…

C++11 FAQ中文版:std::function 和 std::bind

std::function 和 std::bind 标准库函数bind()和function()定义于头文件中&#xff08;该头文件还包括许多其他函数对象&#xff09;&#xff0c;用于处理函数及函数参数。bind()接受一个函数&#xff08;或者函数对象&#xff0c;或者任何你可以通过”(…)”符号调用的事物&am…

Java 习题(面向对象)

1.&#xff08;面向对象基础&#xff09;写一个Worker 类&#xff0c;并创建多个Worker 对象。 为Worker 类添加四个属性&#xff0c; <1>int 类型的id&#xff0c;表示工人的编号&#xff1b; <2>String 类型的name&#xff0c;表示工人的姓名&#xff1b; <3…

机器学习笔记(2):单变量线性回归

目录 1&#xff09;Model representation 2&#xff09;Cost function 3&#xff09;Cost function intuition 1 4&#xff09;Cost function intuition2 5&#xff09;Gradient descent 6&#xff09;Gradient descent intuition 7&#xff09;Gradient descent for li…

指针右左法则----复杂指针解析

其实如果写得出&#xff08;其实不难&#xff09;指针和数组的声明的EBNF的话&#xff0c;那么直接看就可以反应过来了…… 右左法则是一个既著名又常用的方法。不过&#xff0c;右左法则其实并不是C标准里面的内容&#xff0c;它是从C标准的声明规定中归纳出来的方法。C标准的…

【POJ - 3694】Network(对dfn求lca 或 缩点+lca 或 边双连通+并查集)

题干&#xff1a; 网络管理员管理大型网络。该网络由N台计算机和成对计算机之间的M链路组成。任何一对计算机都通过连续的链接直接或间接连接&#xff0c;因此可以在任何两台计算机之间转换数据。管理员发现某些链接对网络至关重要&#xff0c;因为任何一个链接的故障都可能导…

安装VMware tools

点击“虚拟机” 安装VMware tools提取图中文件到“下载” 提取登入root 进入 cd 下载/vmware-tools-distrib 执行 ./vmware-install-pl 输入yes或者点击“enter”出现图中&#xff0c;即为成功安装

Keras入门实战(1):MNIST手写数字分类

目录 1)首先我们加载Keras中的数据集 2&#xff09;网络架构 3&#xff09;选择编译(compile参数) 4&#xff09;准备图像数据 5) 训练模型 6&#xff09;测试数据 前面的博客中已经介绍了如何在Ubuntu下安装Keras深度学习框架。 现在我们使用 Keras 库来学习手写数字分…