当前位置:   article > 正文

(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. /* 1、用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G。
  2.   2、用户A选择一个私有密钥k,并生成公开密钥K=kG。
  3.   3、用户A将Ep(a,b)和点K,G传给用户B。
  4.   4、用户B接到信息后 ,将待传输的明文编码到Ep(a,b)上一点M,并产生一个随机整数r(r<n)。
  5.   5、用户B计算点C1=M+rK;C2=rG。
  6.   6、用户B将C1、C2传给用户A。
  7.   7、用户A接到信息后,计算C1-kC2,结果就是点M。因为
  8. C1-kC2=M+rK-k(rG)=M+rK-r(kG)=M
  9.    再对点M进行解码就可以得到明文。
  10.   密码学中,描述一条Fp上的椭圆曲线,常用到六个参量:
  11. T=(p,a,b,G,n,h)。
  12.   (p 、a 、b 用来确定一条椭圆曲线,G为基点,n为点G的阶,h 是椭圆曲线上所有点的个数m与n相除的整数部分)
  13.   这几个参量取值的选择,直接影响了加密的安全性。参量值一般要求满足以下几个条件:
  14.   1、p 当然越大越安全,但越大,计算速度会变慢,200位左右可以满足一般安全要求;
  15.   2、p≠n×h;
  16.   3、pt≠1 (mod n),1≤t<20;
  17.   4、4a3+27b2≠0 (mod p);
  18.   5、n 为素数;
  19.   6、h≤4。
  20. */
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <stdlib.h>
  24. #include <iostream>
  25. #include "tommath.h"
  26. #include <time.h>
  27. #define BIT_LEN 800
  28. #define KEY_LONG 128 //私钥比特长
  29. #define P_LONG 200 //有限域P比特长
  30. #define EN_LONG 40 //一次取明文字节数(x,20)(y,20)
  31. //得到lon比特长素数
  32. int GetPrime(mp_int *m,int lon);
  33. //得到B和G点X坐标G点Y坐标
  34. void Get_B_X_Y(mp_int *x1,mp_int *y1,mp_int *b, mp_int *a, mp_int *p);
  35. //点乘
  36. 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);
  37. //点加
  38. 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);
  39. //二进制存储密文
  40. int chmistore(mp_int *a,FILE *fp);
  41. //把读取的字符存入mp_int型数
  42. int putin(mp_int *a,char *ch,int chlong);
  43. //ECC加密
  44. void Ecc_encipher(mp_int *qx,mp_int *qy, mp_int *px, mp_int *py,mp_int *a,mp_int *p);
  45. //ECC解密
  46. void Ecc_decipher(mp_int *k, mp_int *a,mp_int *p);
  47. //实现将mp_int数a中的比特串还原为字符串并赋给字符串ch:
  48. int chdraw(mp_int *a,char *ch);
  49. //取密文
  50. int miwendraw(mp_int *a,char *ch,int chlong);
  51. int myrng(unsigned char *dst, int len, void *dat)
  52. {
  53. int x;
  54. for (x = 0; x < len; x++) dst[x] = rand() & 0xFF;
  55. return len;
  56. }
  57. using namespace std;
  58. int main(){
  59. cout<<"\n 本程序实现椭圆曲线的加密解密"<<endl;
  60. cout<<"\n------------------------------------------------------------------------\n"<<endl;
  61. mp_int GX;
  62. mp_int GY;
  63. mp_int K;//私有密钥
  64. mp_int A;
  65. mp_int B;
  66. mp_int QX;
  67. mp_int QY;
  68. mp_int P;//Fp中的p(有限域P)
  69. mp_init(&GX);
  70. mp_init(&GY);
  71. mp_init(&K);
  72. mp_init(&A);
  73. mp_init(&B);
  74. mp_init(&QX);
  75. mp_init(&QY);
  76. mp_init(&P);
  77. time_t t;
  78. srand( (unsigned) time( &t ) );
  79. printf("椭圆曲线的参数如下(以十进制显示):\n");
  80. GetPrime(&P,P_LONG);
  81. printf("有限域 P 是:\n");
  82. char temp[800]={0};
  83. mp_toradix(&P,temp,10);
  84. printf("%s\n",temp);
  85. GetPrime(&A,30);
  86. char tempA[800]={0};
  87. printf("曲线参数 A 是:\n");
  88. mp_toradix(&A,tempA,10);
  89. printf("%s\n",tempA);
  90. Get_B_X_Y(&GX,&GY,&B,&A,&P);
  91. char tempB[800]={0};
  92. printf("曲线参数 B 是:\n");
  93. mp_toradix(&B,tempB,10);
  94. printf("%s\n",tempB);
  95. char tempGX[800]={0};
  96. printf("曲线G点X坐标是:\n");
  97. mp_toradix(&GX,tempGX,10);
  98. printf("%s\n",tempGX);
  99. char tempGY[800]={0};
  100. printf("曲线G点Y坐标是:\n");
  101. mp_toradix(&GY,tempGY,10);
  102. printf("%s\n",tempGY);
  103. //------------------------------------------------------------------
  104. GetPrime(&K,KEY_LONG);
  105. char tempK[800]={0};
  106. printf("私钥 K 是:\n");
  107. mp_toradix(&K,tempK,10);
  108. printf("%s\n",tempK);
  109. Ecc_points_mul(&QX,&QY,&GX,&GY,&K,&A,&P);
  110. char tempQX[800]={0};
  111. printf("公钥X坐标是:\n");
  112. mp_toradix(&QX,tempQX,10);
  113. printf("%s\n",tempQX);
  114. char tempQY[800]={0};
  115. printf("公钥Y坐标是:\n");
  116. mp_toradix(&QY,tempQY,10);
  117. printf("%s\n",tempQY);
  118. printf("\n------------------------------------------------------------------------\n");
  119. Ecc_encipher(&QX,&QY,&GX,&GY,&A,&P);//加密
  120. printf("\n------------------------------------------------------------------------\n");
  121. Ecc_decipher(&K,&A,&P);//解密
  122. printf("\n------------------------------------------------------------------------\n");
  123. char cc;
  124. cout<<"\n\n请击一键退出!\n";
  125. cin>>cc;
  126. mp_clear(&GX);
  127. mp_clear(&GY);
  128. mp_clear(&K);//私有密钥
  129. mp_clear(&A);
  130. mp_clear(&B);
  131. mp_clear(&QX);
  132. mp_clear(&QY);
  133. mp_clear(&P);//Fp中的p(有限域P)
  134. return 0;
  135. }
  136. int GetPrime(mp_int *m,int lon){
  137. mp_prime_random_ex(m, 10, lon,
  138. (rand()&1)?LTM_PRIME_2MSB_OFF:LTM_PRIME_2MSB_ON, myrng, NULL);
  139. return MP_OKAY;
  140. }
  141. void Get_B_X_Y(mp_int *x1,mp_int *y1,mp_int *b, mp_int *a, mp_int *p)
  142. {
  143. mp_int tempx,tempy;
  144. mp_int temp;
  145. mp_int compare;
  146. mp_int temp1;
  147. mp_int temp2;
  148. mp_int temp3;
  149. mp_int temp4;
  150. mp_int temp5;
  151. mp_int temp6;
  152. mp_int temp7;
  153. mp_int temp8;
  154. mp_init_set_int (&compare, 0);
  155. mp_init(&tempx);
  156. mp_init(&tempy);
  157. mp_init(&temp);
  158. mp_init(&temp1);
  159. mp_init(&temp2);
  160. mp_init(&temp3);
  161. mp_init(&temp4);
  162. mp_init(&temp5);
  163. mp_init(&temp6);
  164. mp_init(&temp7);
  165. mp_init(&temp8);
  166. while(1)
  167. {
  168. //4a3+27b2≠0 (mod p)
  169. GetPrime(b,40);
  170. mp_expt_d(a, 3, &temp1);
  171. mp_sqr(b, &temp2);
  172. mp_mul_d(&temp1, 4, &temp3);
  173. mp_mul_d(&temp2, 27, &temp4);
  174. mp_add(&temp3, &temp4, &temp5);
  175. mp_mod(&temp5,p,&temp);
  176. if(mp_cmp(&temp, &compare)!=0 )
  177. {
  178. break;
  179. }
  180. }
  181. //y2=x3+ax+b,随机产生X坐标,根据X坐标计算Y坐标
  182. GetPrime(x1,30);
  183. mp_expt_d(x1, 3, &temp6);
  184. mp_mul(a, x1, &temp7);
  185. mp_add(&temp6, &temp7, &temp8);
  186. mp_add(&temp8, b, &tempx);
  187. mp_sqrt(&tempx, y1);
  188. mp_clear(&tempx);
  189. mp_clear(&tempy);
  190. mp_clear(&temp);
  191. mp_clear(&temp1);
  192. mp_clear(&temp2);
  193. mp_clear(&temp3);
  194. mp_clear(&temp4);
  195. mp_clear(&temp5);
  196. mp_clear(&temp6);
  197. mp_clear(&temp7);
  198. mp_clear(&temp8);
  199. }
  200. 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)
  201. {
  202. mp_int X1, Y1;
  203. mp_int X2, Y2;
  204. mp_int X3, Y3;
  205. mp_int XX1, YY1;
  206. mp_int A,P;
  207. int i;
  208. bool zero=false;
  209. char Bt_array[800]={0};
  210. char cm='1';
  211. mp_toradix(d,Bt_array,2);
  212. mp_init_set_int(&X3, 0);
  213. mp_init_set_int(&Y3, 0);
  214. mp_init_copy(&X1, px);
  215. mp_init_copy(&X2, px);
  216. mp_init_copy(&XX1, px);
  217. mp_init_copy(&Y1, py);
  218. mp_init_copy(&Y2, py);
  219. mp_init_copy(&YY1, py);
  220. mp_init_copy(&A, a);
  221. mp_init_copy(&P, p);
  222. for(i=1;i<=KEY_LONG-1;i++)
  223. {
  224. mp_copy(&X2, &X1);
  225. mp_copy(&Y2, &Y1);
  226. Two_points_add(&X1,&Y1,&X2,&Y2,&X3,&Y3,&A,zero,&P);
  227. mp_copy(&X3, &X2);
  228. mp_copy(&Y3, &Y2);
  229. if(Bt_array[i]==cm)
  230. {
  231. mp_copy(&XX1, &X1);
  232. mp_copy(&YY1, &Y1);
  233. Two_points_add(&X1,&Y1,&X2,&Y2,&X3,&Y3,&A,zero,&P);
  234. mp_copy(&X3, &X2);
  235. mp_copy(&Y3, &Y2);
  236. }
  237. }
  238. if(zero)
  239. {
  240. cout<<"It is Zero_Unit!";
  241. return false;//如果Q为零从新产生D
  242. }
  243. mp_copy(&X3, qx);
  244. mp_copy(&Y3, qy);
  245. mp_clear(&X1);
  246. mp_clear(&Y1);
  247. mp_clear(&X2);
  248. mp_clear(&Y2);
  249. mp_clear(&X3);
  250. mp_clear(&Y3);
  251. mp_clear(&XX1);
  252. mp_clear(&YY1);
  253. mp_clear(&A);
  254. mp_clear(&P);
  255. return true;
  256. }
  257. //两点加
  258. 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)
  259. {
  260. mp_int x2x1;
  261. mp_int y2y1;
  262. mp_int tempk;
  263. mp_int tempy;
  264. mp_int tempzero;
  265. mp_int k;
  266. mp_int temp1;
  267. mp_int temp2;
  268. mp_int temp3;
  269. mp_int temp4;
  270. mp_int temp5;
  271. mp_int temp6;
  272. mp_int temp7;
  273. mp_int temp8;
  274. mp_int temp9;
  275. mp_int temp10;
  276. mp_init(&x2x1);
  277. mp_init(&y2y1);
  278. mp_init(&tempk);
  279. mp_init(&tempy);
  280. mp_init(&tempzero);
  281. mp_init(&k);
  282. mp_init(&temp1);
  283. mp_init(&temp2);
  284. mp_init_set(&temp3,2);
  285. mp_init(&temp4);
  286. mp_init(&temp5);
  287. mp_init(&temp6);
  288. mp_init(&temp7);
  289. mp_init(&temp8);
  290. mp_init(&temp9);
  291. mp_init(&temp10);
  292. if(zero)
  293. {
  294. mp_copy(x1, x3);
  295. mp_copy(y1, y3);
  296. zero=false;
  297. goto L;
  298. }
  299. mp_zero(&tempzero);
  300. mp_sub(x2, x1, &x2x1);
  301. if(mp_cmp(&x2x1,&tempzero)==-1)
  302. {
  303. mp_add(&x2x1, p, &temp1);
  304. mp_zero(&x2x1);
  305. mp_copy(&temp1, &x2x1);
  306. }
  307. mp_sub(y2, y1, &y2y1);
  308. if(mp_cmp(&y2y1,&tempzero)==-1)
  309. {
  310. mp_add(&y2y1, p, &temp2);
  311. mp_zero(&y2y1);
  312. mp_copy(&temp2, &y2y1);
  313. }
  314. if(mp_cmp(&x2x1, &tempzero)!=0)
  315. {
  316. mp_invmod(&x2x1,p,&tempk);
  317. mp_mulmod(&y2y1, &tempk, p, &k);
  318. }
  319. else
  320. {
  321. if(mp_cmp(&y2y1, &tempzero)==0)
  322. {
  323. mp_mulmod(&temp3,y1,p,&tempy);
  324. mp_invmod(&tempy,p,&tempk);
  325. mp_sqr(x1, &temp4);
  326. mp_mul_d(&temp4, 3, &temp5);
  327. mp_add(&temp5, a, &temp6);
  328. mp_mulmod(&temp6, &tempk, p, &k);
  329. }
  330. else
  331. {
  332. zero=true;
  333. goto L;
  334. }
  335. }
  336. mp_sqr(&k, &temp7);
  337. mp_sub(&temp7, x1, &temp8);
  338. mp_submod(&temp8, x2, p, x3);
  339. mp_sub(x1, x3, &temp9);
  340. mp_mul(&temp9, &k, &temp10);
  341. mp_submod(&temp10, y1, p, y3);
  342. L:
  343. mp_clear(&x2x1);
  344. mp_clear(&y2y1);
  345. mp_clear(&tempk);
  346. mp_clear(&tempy);
  347. mp_clear(&tempzero);
  348. mp_clear(&k);
  349. mp_clear(&temp1);
  350. mp_clear(&temp2);
  351. mp_clear(&temp3);
  352. mp_clear(&temp4);
  353. mp_clear(&temp5);
  354. mp_clear(&temp6);
  355. mp_clear(&temp7);
  356. mp_clear(&temp8);
  357. mp_clear(&temp9);
  358. mp_clear(&temp10);
  359. return 1;
  360. }
  361. //二进制存储密文
  362. int chmistore(mp_int *a,FILE *fp)
  363. {
  364. int i,j;
  365. char ch;
  366. char chtem[4];
  367. mp_digit yy=(mp_digit)255;
  368. for (i=0; i <= a->used - 1; i++) {
  369. chtem[3]=(char)(a->dp[i] & yy);
  370. chtem[2]=(char)((a->dp[i] >> (mp_digit)8) & yy);
  371. chtem[1]=(char)((a->dp[i] >> (mp_digit)16) & yy);
  372. chtem[0]=(char)((a->dp[i] >> (mp_digit)24) & yy);
  373. for(j=0;j<4;j++)
  374. {
  375. fprintf(fp,"%c",chtem[j]);
  376. }
  377. }
  378. ch=char(255);
  379. fprintf(fp, "%c", ch);
  380. return MP_OKAY;
  381. }
  382. //把读取的字符存入mp_int型数
  383. int putin(mp_int *a,char *ch,int chlong)
  384. {
  385. mp_digit *temp,yy;
  386. int i,j,res;
  387. if(a->alloc<chlong*2/7+2)
  388. {
  389. if((res=mp_grow(a,chlong*2/7+2))!=MP_OKAY)
  390. return res;
  391. }
  392. a->sign=0;
  393. mp_zero(a);
  394. temp=a->dp;
  395. i=0;
  396. yy=(mp_digit)15;
  397. if(chlong<4)
  398. {
  399. for(j=chlong-1;j>=0;j--)
  400. {
  401. *temp |= (mp_digit)(ch[j] & 255);
  402. *temp <<= (mp_digit)CHAR_BIT;
  403. }
  404. *temp >>= (mp_digit)8;
  405. a->used=1;
  406. return MP_OKAY;
  407. }
  408. if(chlong<7)
  409. {
  410. i+=4;
  411. *++temp |= (mp_digit)(ch[i-1] & yy);
  412. *temp <<= (mp_digit)CHAR_BIT;
  413. *temp |= (mp_digit)(ch[i-2] & 255);
  414. *temp <<= (mp_digit)CHAR_BIT;
  415. *temp |= (mp_digit)(ch[i-3] & 255);
  416. *temp <<= (mp_digit)CHAR_BIT;
  417. *temp-- |= (mp_digit)(ch[i-4] & 255); //存放被切分的字符的低四位
  418. for(j=chlong-1;j>=i;j--)
  419. {
  420. *temp |= (mp_digit)(ch[j] & 255);
  421. *temp <<= (mp_digit)CHAR_BIT;
  422. }
  423. *temp >>= (mp_digit)4;
  424. *temp |= (mp_digit)((ch[i-1] & 255) >> 4); //存放被切分的字符的高四位
  425. a->used=2;
  426. return MP_OKAY;
  427. }
  428. //以7个字符为单元循环,把七个字符放入的mp_int 的两个单元中
  429. for(j=0;j<chlong/7;j++)
  430. {
  431. i+=7;
  432. *++temp |= (mp_digit)(ch[i-1] & 255);
  433. *temp <<= (mp_digit)CHAR_BIT;
  434. *temp |= (mp_digit)(ch[i-2] & 255);
  435. *temp <<= (mp_digit)CHAR_BIT;
  436. *temp |= (mp_digit)(ch[i-3] & 255);
  437. *temp <<= (mp_digit)4;
  438. *temp-- |= (mp_digit)((ch[i-4] & 255) >> 4); //存放被切分的字符的高四位
  439. *temp |= (mp_digit)(ch[i-4] & yy); //存放被切分的字符的低四位
  440. *temp <<= (mp_digit)CHAR_BIT;
  441. *temp |= (mp_digit)(ch[i-5] & 255);
  442. *temp <<= (mp_digit)CHAR_BIT;
  443. *temp |= (mp_digit)(ch[i-6] & 255);
  444. *temp <<= (mp_digit)CHAR_BIT;
  445. *temp++ |= (mp_digit)(ch[i-7] & 255);
  446. temp++;
  447. }
  448. if((chlong>=7)&&(chlong%7!=0)) //剩余字符的存放
  449. {
  450. if(chlong%7 < 4) //剩余字符少余4个时,只需一个mp_digit单元存放
  451. {
  452. for(j=chlong-1;j>=i;j--)
  453. {
  454. *temp |= (mp_digit)(ch[j] & 255);
  455. *temp <<= (mp_digit)CHAR_BIT;
  456. }
  457. *temp >>= (mp_digit)8;
  458. a->used=chlong*2/7+1;
  459. }
  460. else
  461. { //剩余字符不小于4个时,需两个mp_digit单元存放
  462. i+=4;
  463. *temp |= (mp_digit)(ch[i-1] & yy);
  464. *temp <<= (mp_digit)CHAR_BIT;
  465. *temp |= (mp_digit)(ch[i-2] & 255);
  466. *temp <<= (mp_digit)CHAR_BIT;
  467. *temp |= (mp_digit)(ch[i-3] & 255);
  468. *temp <<= (mp_digit)CHAR_BIT;
  469. *temp++ |= (mp_digit)(ch[i-4] & 255); //存放被切分的字符的低四位
  470. for(j=chlong-1;j>=i;j--)
  471. {
  472. *temp |= (mp_digit)(ch[j] & 255);
  473. *temp <<= (mp_digit)CHAR_BIT;
  474. }
  475. *temp >>= (mp_digit)4;
  476. *temp |= (mp_digit)((ch[i-1] & 255) >> 4); //存放被切分的字符的高四位
  477. a->used=chlong*2/7+2;
  478. }
  479. }
  480. else
  481. {
  482. a->used=chlong*2/7;
  483. }
  484. return MP_OKAY;
  485. }
  486. 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,有限域P
  487. mp_int mx, my;
  488. mp_int c1x, c1y;
  489. mp_int c2x, c2y;
  490. mp_int r;
  491. mp_int tempx, tempy;
  492. bool zero=false;
  493. FILE *fp,*fq;
  494. int i;
  495. char miwenx[280]={0};
  496. char miweny[280]={0};
  497. char stemp[650]={0};
  498. mp_init(&mx);
  499. mp_init(&my);
  500. mp_init(&c1x);
  501. mp_init(&c1y);
  502. mp_init(&c2x);
  503. mp_init(&c2y);
  504. mp_init(&r);
  505. mp_init(&tempx);
  506. mp_init(&tempy);
  507. GetPrime(&r, 100);
  508. char filehead[60],filefoot[20],filename[85]={0};
  509. cout<<"请输入您要加密文件的存放路径和文件名(如: c:\\000\\大整数运算 ):"<<endl;
  510. cin>>filehead;
  511. cout<<"请输入您要加密文件的扩展名(如: .doc ):"<<endl;
  512. cin>>filefoot;
  513. strcpy(filename,filehead);
  514. strcat(filename,filefoot);
  515. //打开要加密文件
  516. if((fp=fopen(filename,"rb"))==NULL)
  517. {
  518. printf("can not open the file!");
  519. exit(1);
  520. }
  521. unsigned int FileLong=0;//文件字符长度
  522. char ChTem;//临时字符变
  523. int Frequency=0;
  524. int Residue=0;
  525. while( !feof(fp) )//找文件字符长度
  526. {
  527. ChTem = fgetc( fp );
  528. FileLong++;
  529. }
  530. --FileLong;
  531. Frequency = FileLong/EN_LONG;
  532. Residue = FileLong%EN_LONG;
  533. printf("Frequency= %d, Residue= %d\n", Frequency, Residue);
  534. int enlongtemp=EN_LONG/2;
  535. //printf("%d\n",Frequency);
  536. //printf("%d\n",Residue);
  537. char filemi[85];
  538. strcpy(filemi,filehead);
  539. strcat(filemi,"密文");
  540. strcat(filemi,filefoot);
  541. //打开保存密文文件
  542. if((fq=fopen(filemi,"wb"))==NULL)
  543. {
  544. printf("can not open the file!\n");
  545. exit(1);
  546. }
  547. printf("\n开始加密...\n");
  548. rewind(fp);
  549. clock_t start, finish;
  550. double duration;
  551. for(i=0; i<Frequency; i++)
  552. {
  553. fread(miwenx,1,enlongtemp,fp);//读入字符串
  554. miwenx[enlongtemp]=char(255);
  555. fread(miweny,1,enlongtemp,fp);//读入字符串
  556. miweny[enlongtemp]=char(255);
  557. putin(&mx, miwenx,enlongtemp+1);//文件存入
  558. putin(&my, miweny,enlongtemp+1);//文件存入
  559. Ecc_points_mul(&c2x,&c2y,px,py,&r,a,p);//加密
  560. Ecc_points_mul(&tempx,&tempy,qx,qy,&r,a,p);
  561. Two_points_add(&mx,&my,&tempx,&tempy,&c1x,&c1y,a,zero,p);
  562. //保存密文
  563. chmistore(&c1x,fq);
  564. chmistore(&c1y,fq);
  565. chmistore(&c2x,fq);
  566. chmistore(&c2y,fq);
  567. }
  568. //剩余字符处理
  569. if ( Residue > 0)
  570. {
  571. if (Residue <= enlongtemp )
  572. {
  573. fread(miwenx,1,Residue,fp);//读入字符串
  574. miwenx[Residue]=char(255);
  575. putin(&mx, miwenx,Residue+1);//文件存入
  576. mp_zero(&my);
  577. }
  578. else
  579. {
  580. fread(miwenx,1,enlongtemp,fp);//读入字符串
  581. miwenx[enlongtemp]=char(255);
  582. fread(miweny,1,Residue-enlongtemp,fp);//读入字符串
  583. miweny[Residue-enlongtemp]=char(255);
  584. putin(&mx, miwenx,enlongtemp+1);//文件存入
  585. putin(&my, miweny,Residue-enlongtemp+1);//文件存入
  586. }
  587. Ecc_points_mul(&c2x,&c2y,px,py,&r,a,p);//加密
  588. Ecc_points_mul(&tempx,&tempy,qx,qy,&r,a,p);
  589. Two_points_add(&mx,&my,&tempx,&tempy,&c1x,&c1y,a,zero,p);
  590. //保存密文
  591. chmistore(&c1x,fq);
  592. chmistore(&c1y,fq);
  593. chmistore(&c2x,fq);
  594. chmistore(&c2y,fq);
  595. }
  596. cout<<"\nok!加密完毕!"<<endl;
  597. cout<<"密文以二进制保存"<<endl;
  598. cout<<"密文存放路径为 "<<filemi<<endl ;
  599. fclose(fq);
  600. fclose(fp);
  601. mp_clear(&mx);
  602. mp_clear(&my);
  603. mp_clear(&c1x);
  604. mp_clear(&c1y);
  605. mp_clear(&c2x);
  606. mp_clear(&c2y);
  607. mp_clear(&r);
  608. mp_clear(&tempx);
  609. mp_clear(&tempy);
  610. }
  611. //取密文
  612. int miwendraw(mp_int *a,char *ch,int chlong)
  613. {
  614. mp_digit *temp;
  615. int i,j,res;
  616. if(a->alloc<chlong/4)
  617. {
  618. if((res=mp_grow(a,chlong/4))!=MP_OKAY)
  619. return res;
  620. }
  621. a->alloc=chlong/4;
  622. a->sign=0;
  623. mp_zero(a);
  624. temp=a->dp;
  625. i=0;
  626. for(j=0;j<chlong/4;j++)
  627. {
  628. i+=4;
  629. *temp |= (mp_digit)(ch[i-4] & 255);
  630. *temp <<= (mp_digit)CHAR_BIT;
  631. *temp |= (mp_digit)(ch[i-3] & 255);
  632. *temp <<= (mp_digit)CHAR_BIT;
  633. *temp |= (mp_digit)(ch[i-2] & 255);
  634. *temp <<= (mp_digit)CHAR_BIT;
  635. *temp++ |= (mp_digit)(ch[i-1] & 255);
  636. }
  637. a->used=chlong/4;
  638. return MP_OKAY;
  639. }
  640. //实现将mp_int数a中的比特串还原为字符串并赋给字符串ch:
  641. int chdraw(mp_int *a,char *ch)
  642. {
  643. int i,j;
  644. mp_digit *temp,xx,yy;
  645. temp=a->dp;
  646. i=0;
  647. yy=(mp_digit)255; //用于位与运算,取八位比特串
  648. xx=(mp_digit)15; //用于位与运算,取四位比特串
  649. for(j=0;j<a->used/2;j++) //以两个单元为循环,把两个单元的比特串赋给7个字符
  650. {
  651. i+=7;
  652. ch[i-4]=(char)(*++temp & xx);
  653. ch[i-3]=(char)((*temp >> (mp_digit)4) & yy);
  654. ch[i-2]=(char)((*temp >> (mp_digit)12) & yy);
  655. ch[i-1]=(char)((*temp-- >> (mp_digit)20) & yy);
  656. ch[i-7]=(char)(*temp & yy);
  657. ch[i-6]=(char)((*temp >> (mp_digit)8) & yy);
  658. ch[i-5]=(char)((*temp >> (mp_digit)16) & yy);
  659. ch[i-4] <<= 4;
  660. ch[i-4]+=(char)((*temp++ >> (mp_digit)24) & xx);
  661. temp++;
  662. }
  663. if(a->used%2!=0) //剩于一个单元的处理
  664. {
  665. ch[i++] = (char)(*temp & yy);
  666. ch[i++] = (char)((*temp >> (mp_digit)8) & yy);
  667. ch[i++] = (char)((*temp >> (mp_digit)16) & yy);
  668. }
  669. --i;
  670. while(int(ch[i]&0xFF) != 255 && i>0) i--;
  671. return i;
  672. }
  673. void Ecc_decipher(mp_int *k, mp_int *a,mp_int *p){
  674. mp_int c1x, c1y;
  675. mp_int c2x, c2y;
  676. mp_int tempx, tempy;
  677. mp_int mx, my;
  678. mp_int temp;
  679. mp_init(&temp);
  680. mp_init(&c1x);
  681. mp_init(&c1y);
  682. mp_init(&c2x);
  683. mp_init(&c2y);
  684. mp_init(&tempx);
  685. mp_init(&tempy);
  686. mp_init(&mx);
  687. mp_init(&my);
  688. mp_int tempzero;
  689. mp_init(&tempzero);
  690. int i;
  691. char stemp[700]={0};
  692. FILE *fp,*fq;
  693. bool zero=false;
  694. clock_t start, finish;
  695. double duration;
  696. char filehead[60],filefoot[20],filename[85]={0};
  697. cout<<"请输入您要解密的文件的存放路径和文件名(如: c:\\000\\大整数运算 ):"<<endl;
  698. cin>>filehead;
  699. cout<<"请输入您要解密的文件的扩展名(如: .doc ):"<<endl;
  700. cin>>filefoot;
  701. strcpy(filename,filehead);
  702. strcat(filename,filefoot);
  703. printf("\n开始解密\n");
  704. if((fp=fopen(filename,"rb"))==NULL)
  705. {
  706. printf("can not open the file!");
  707. exit(1);
  708. }
  709. //打开保存解密结果文件
  710. char filemi[80];
  711. strcpy(filemi, filehead);
  712. strcat(filemi, "解密");
  713. strcat(filemi, filefoot);
  714. if((fq=fopen(filemi,"wb"))==NULL)
  715. {
  716. printf("can not open the file!");
  717. exit(1);
  718. }
  719. rewind(fp);
  720. while(!feof(fp))
  721. {
  722. i=0;
  723. while(1)
  724. {
  725. stemp[i]=fgetc(fp);
  726. if(i%4==0)
  727. {
  728. if(int(stemp[i]&0xFF) == 255 ) goto L1;
  729. }
  730. i++;
  731. }
  732. L1: miwendraw(&c1x, stemp, i);
  733. i=0;
  734. while(1)
  735. {
  736. stemp[i]=fgetc(fp);
  737. if(i%4==0)
  738. {
  739. if(int(stemp[i]&0xFF) == 255 ) goto L2;
  740. }
  741. i++;
  742. }
  743. L2: miwendraw(&c1y, stemp, i);
  744. i=0;
  745. while(1)
  746. {
  747. stemp[i]=fgetc(fp);
  748. if(i%4==0)
  749. {
  750. if(int(stemp[i]&0xFF) == 255 ) goto L3;
  751. }
  752. i++;
  753. }
  754. L3: miwendraw(&c2x, stemp, i);
  755. i=0;
  756. while(1)
  757. {
  758. stemp[i]=fgetc(fp);
  759. if(i%4==0)
  760. {
  761. if(int(stemp[i]&0xFF) == 255 ) goto L4;
  762. }
  763. i++;
  764. }
  765. L4: miwendraw(&c2y, stemp, i);
  766. mp_zero(&tempzero);
  767. if(mp_cmp(&c1x, &tempzero)==0) break;
  768. Ecc_points_mul(&tempx, &tempy, &c2x, &c2y, k, a, p);
  769. mp_neg(&tempy, &temp);
  770. Two_points_add(&c1x,&c1y,&tempx,&temp,&mx,&my,a,zero,p);
  771. int chtem;
  772. chtem=chdraw(&mx,stemp);//从ming中取出字符串
  773. //保存解密结果
  774. for(int kk=0;kk<chtem;kk++)
  775. {
  776. fprintf(fq,"%c",stemp[kk]);
  777. }
  778. chtem=chdraw(&my,stemp);//从ming中取出字符串
  779. //保存解密结果
  780. for(int kk=0;kk<chtem;kk++)
  781. {
  782. fprintf(fq,"%c",stemp[kk]);
  783. }
  784. }
  785. cout<<"\nok!解密完毕!"<<endl;
  786. cout<<"解密后的文字存放路径为 "<<filemi<<endl;
  787. fclose(fq);
  788. fclose(fp);
  789. mp_clear(&c1x);
  790. mp_clear(&c1y);
  791. mp_clear(&c2x);
  792. mp_clear(&c2y);
  793. mp_clear(&tempx);
  794. mp_clear(&tempy);
  795. mp_clear(&mx);
  796. mp_clear(&my);
  797. mp_clear(&temp);
  798. }

在命令行执行:

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

生成可执行文件main。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/731216
推荐阅读
相关标签
  

闽ICP备14008679号