目录

(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。

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

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

    /* 1.用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G.2.用户A选择一个私有密钥k,并生成公开密钥K=kG.3.用户A将Ep(a,b)和 ...

  2. 公钥加密技术ECC椭圆曲线加密算法原理

    同样来自B站不错的视频讲解:公钥加密技术ECC椭圆曲线加密算法原理_哔哩哔哩_bilibili 就曲线上A点,过B点,第3点如果也交在曲线上的话,再做一次镜像,就肯定得到C点,那么这个就叫做点运算. ...

  3. ECC椭圆曲线加密算法原理

    比特币使用椭圆曲线算法生成公钥和私钥,选择的是secp256k1曲线.与RSA(Ron Rivest,Adi Shamir,Len Adleman三位天才的名字)一样,ECC(Elliptic Cur ...

  4. ECC椭圆曲线加密算法原理 | 比特币加密算法

    比特币使用椭圆曲线算法生成公钥和私钥,选择的是secp256k1曲线.与RSA(Ron Rivest,Adi Shamir,Len Adleman三位天才的名字)一样,ECC(Elliptic Cur ...

  5. ecc椭圆加密算法c语言,ECC 椭圆曲线加密算法学习————ECDH与ECDSA

    0x00 前言 之前学习了实数域上的椭圆曲线与有限域$\mathbb {F}_{p}$上的椭圆曲线.详细可以参考ECC椭圆加密算法学习----从实数域到有限域的椭圆曲线. 不难发现,在实数域的标量乘法 ...

  6. SM4分组加密算法原理和c语言实现

    一.前言 在之前的文章中介绍了<SM3国密杂凑值算法的原理和c语言实现>,这篇文章主要是用c语言撸一个SM4分组加密算法. 随着信息安全的普及以及等级保护等安全政策落地,国密算法越来越频繁 ...

  7. RSA加密算法原理和java简单实现

    数学 RSA加密算法中,用到素数.互质数.指数运算.模运算等几个数学知识. 素数 素数又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数. 互质数 百度百科:公因数只有 ...

  8. 椭圆曲线标量乘法快速算法(附源码实现)

    一.椭圆曲线密码算法 椭圆曲线密码算法(elliptic curve cryptograph,ECC)是一类重要的密码算法.椭圆曲线有如下性质: 有限域上椭圆曲线在点加运算下构成有限交换群,且阶与基域 ...

  9. 反编译.class和原java文件的源码对比

    大家都知道,java文件编译后是.class文件,如果我们通过反编译的方式,重新反编译成java文件,此java文件和原来编译前的java文件有什么区别呢? 下面主要对比字面型常量之间.变量之间以及两 ...

最新文章

  1. Latex中的表格用法总结(三)——表格的合并分割,字体旋转,表头语句切割
  2. 1.14 梯度检验应用的注意事项-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  3. 开始复习下sql,常用SQL语句示例(一)
  4. PAT1053 住房空置率 (20 分)
  5. .rpt文件内容读取java_Java快速入门(26) 文件和IO操作
  6. html5 上海,【上海校区】HTML5新特性
  7. 问题1、图像分割预测时原始图片大小与预测图片大小不一致
  8. oracle10g连接自动断开,报ORA-03135错误
  9. Android 音视频开发学习思路大纲
  10. html 设计页面,HTML5网页设计
  11. Oracle | oracle11g安装环境变量配置
  12. html设置等宽字体效果
  13. 手机隐藏Magisk的root痕迹,适用于含zygisk的Magisk
  14. 最全面的Kano模型详解,及Kano模型为何是5种需求?
  15. 无线信道特性分析及建模仿真
  16. Linux 下文件和目录的特点
  17. Python自动化测试系列[v1.0.0][JS完成任务]
  18. 神经网络学习小记录2——利用tensorflow构建循环神经网络(RNN)
  19. Excel将数值转换为按指定数字格式表示的文本
  20. 【Web前端大作业实例网页代码】html+css新闻资讯网页带dw模板和登陆注册(9页)

热门文章

  1. java 爬虫_探索Java 多线程爬虫及分布式爬虫架构
  2. 语言求圆周率近似值改错_新证明解决了如何求无理数的近似值
  3. C# 派生类的构造函数
  4. python发钉钉消息_Python调用钉钉机器人推送消息
  5. 求合体电脑版_网红界宋祖儿找年轻版言承旭当男友,一张合照收割大量cp粉?!...
  6. c语言链表复数实验,数据结构实验—复数计算器 大神提意见
  7. mysql memcached 使用场景_memcache 应用场景
  8. wince6下usb摄像头(UVC)使用指南
  9. 程序员:如何写出杀手级简历
  10. php通过条件来定义const,php用const出错是什么原因