/*
----正在生成椭圆曲线参数----
a=15
b=0
q=79
----椭圆曲线参数生成完成----
****正在生成基点和其阶****
G.x=47
G.y=13
n=5
****基点和其阶生成完成****
----正在生成密钥对---
d=3
Q.x=43
Q.y=58
----密钥对生成完成---
本程序实现椭圆曲线的签名认证和加密解密
------------------------------------------------------------------------
椭圆曲线的参数如下(以十进制显示):
有限域 P 是:
1461501637330902918203684832716283019655932542929
曲线参数 A 是:
5010998137597857324482644726529916424714585
曲线参数 B 是:
1391074318475376408459666168311750783430782
曲线G点X坐标是:
1849774946964655828063549341304231538196971
曲线G点Y坐标是:
106085596239133023520814327459780822844835115629
G点阶是:
1461501637330902918203685121540024994978925914423
n is prime
私钥 sk 是:
3
公钥X坐标是:
422565412993265696736677168788599453568957208023
公钥Y坐标是:
475471833959164653433082276654473277996663194952
h1 9485368595
杭州电子科技大学
ux=983956313527861341041021882601806194699538727560
uy=1267063982440832922234697620521284072829508878899
s=35484935791730502498080488720604609264980372306
h2 9485368595
Authentication OK
Press any key to continue
Let E be the curve
y2 = x3 + 10 x + 5
over the field GF (13). Then the points on E are
{O, (1,4), (1,9), (3,6), (3,7), (8,5), (8,8), (10,0), (11,4), (11,9)}
(3,6) is a generator.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream.h>
#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)
#define Max 0xfff
//得到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);
//点乘
//void 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,mp_int *p);
//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);
//生成密钥对
void SetKey(mp_int*QX,mp_int*QY,mp_int*GX,mp_int*GY,mp_int*sk,mp_int*n,mp_int*A,mp_int*B,mp_int*P);
//检验密钥
bool CheckKey(mp_int*QX,mp_int*QY,mp_int*sk,mp_int*n,mp_int*A,mp_int*B,mp_int*P);
int myrng(unsigned char *dst, int len, void *dat)
{
int x;
for (x = 0; x < len; x++) dst[x] = rand() & 0xFF;
return len;
}
char temp[800];
char *Check(mp_int *mp)
{
mp_toradix(mp,temp,16);
return temp;
}
void 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 X, Y;
unsigned int i;
char Bt_array[800];
mp_toradix(d,Bt_array,2);
mp_zero(qx);
mp_zero(qy);
mp_init(&X);mp_init(&Y);
for(i=0;i<strlen(Bt_array);i++)
{
// printf("here i=%d\n",i);
Two_points_add(qx,qy,qx,qy,&X,&Y,a,p);
mp_copy(&X, qx);
mp_copy(&Y, qy);
if(Bt_array[i]=='1')
{
Two_points_add(qx,qy,px,py,&X,&Y,a,p);
mp_copy(&X, qx);
mp_copy(&Y, qy);
}
}
mp_clear(&X);
mp_clear(&Y);
}
bool Testy(mp_int *temp2, mp_int *y1,mp_int *p)
{
int ret;
mp_is_square(temp2,&ret);
if(ret)
{
mp_sqrt(temp2,y1);
return true;
}
mp_add(temp2,p,temp2);
mp_is_square(temp2,&ret);
if(ret)
{
mp_sqrt(temp2,y1);
return true;
}
mp_add(temp2,p,temp2);
mp_is_square(temp2,&ret);
if(ret)
{
mp_sqrt(temp2,y1);
return true;
}
//printf("ret=%d\n",ret);
return false;
}
//选择基点,并计算其阶
void BasePoint(mp_int *x1,mp_int *y1,mp_int *a, mp_int *b, mp_int *p, mp_int *n)
{
mp_int temp1;
mp_int temp2;
mp_int temp3;
mp_int two;
mp_int four;
mp_int quotient;
mp_int pm1;
mp_int intMax;
mp_int x2,y2,x3,y3;
mp_init(&temp1);mp_init(&temp2);mp_init(&temp3);
mp_init("ient);mp_init(&pm1);mp_init(&intMax);
mp_init(&x2);mp_init(&y2);mp_init(&x3);mp_init(&y3);
mp_copy(p,&intMax);
mp_add(&intMax,p,&intMax);
mp_init_set(&two,2);
mp_init_set(&four,4);
mp_sub_d(p,1,&pm1);
while (mp_cmp(x1,&pm1)==-1)
{
//mp_toradix(x1,temp,10);
//printf("here x1=%s\n",temp);
mp_expt_d(x1, 3, &temp1);
mp_mul(a, x1, &temp2);
mp_add(&temp1, &temp2, &temp3);
mp_add(&temp3, b, &temp1);
mp_mod(&temp1,p,&temp2);
if (mp_cmp_d(&temp2,0)==0)
{
mp_zero(y1);
}
else
{
/* d = a**b (mod c) */
//int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
/* a/b => cb + d == a */
//int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
mp_div(&pm1,&two,"ient,&temp3);
mp_exptmod(&temp2,"ient,p,&temp1);
if (mp_cmp_d(&temp1,1)==0)
{
//A^{(p-1)/2}=1
/* c = a mod b, 0 <= c < b */
//int mp_mod(mp_int *a, mp_int *b, mp_int *c);
mp_mod(p,&four,&temp1);
if (mp_cmp_d(&temp1,3)==0)
{
// p = 4k + 3 for some positive integer k
// output z := g^{k + 1} mod p.
mp_add_d(p,1,&temp1);
mp_div(&temp1,&four,"ient,&temp3);
mp_exptmod(&temp2,"ient,p,y1);
}
else
{
if(!Testy(&temp2,y1,p))
{
mp_add_d(x1,1,x1);
continue;
}
}
}
else
{
if(!Testy(&temp2,y1,p))
{
mp_add_d(x1,1,x1);
continue;
}
}
}
mp_init_set(n,1);
/* copy a to b */
//int mp_copy(mp_int *a, mp_int *b);
mp_copy(x1,&x2);
mp_copy(y1,&y2);
int result;
mp_int tempx;mp_init(&tempx);
mp_int tempy;mp_init(&tempy);
mp_expt_d(x1,3,&tempx);
mp_mod(&tempx,p,&tempx);
/* d = a * b (mod c) */
//int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
mp_mulmod(x1,a,p,&tempy);
mp_addmod(&tempx,&tempy,p,&tempx);
mp_addmod(&tempx,b,p,&tempx);
mp_expt_d(y1,2,&tempy);
mp_mod(&tempy,p,&tempy);
if (mp_cmp(&tempx,&tempy))
{
printf("here2 bad\n\n");
return;
}
//printf("here good\n\n");
//return;
while(1)
{
/*
mp_toradix(x1,temp,10);
printf("here2 x1=%s\n",temp);
mp_toradix(y1,temp,10);
printf("here2 y1=%s\n",temp);
*/
Two_points_add(x1,y1,&x2,&y2,&x3,&y3,a,p);
mp_copy(&x3,&x2);
mp_copy(&y3,&y2);
mp_add_d(n,1,n);
if (mp_cmp(n,&intMax)==1)
{
mp_add_d(x1,1,x1);
break;
}
if (mp_cmp_d(&x2,0)==0 && mp_cmp_d(&y2,0)==0)
{
/* Sets result to 1 if probably prime, 0 otherwise */
// int mp_prime_is_prime(mp_int *a, int t, int *result);
mp_prime_is_prime(n,10,&result);
if (result==1)return;
else
{
//mp_add_d(x1,1,x1);
//break;
mp_zero(n);
return;
}
}
}
}
}
//生成密钥对
void SetKey(mp_int*QX,mp_int*QY,mp_int*GX,mp_int*GY,mp_int*sk,mp_int*n,mp_int*A, mp_int*B,mp_int*P)
{
bool r=false;
char temp[800];
mp_int nm1;mp_init(&nm1);
mp_sub_d(n,1,&nm1);
strcpy(temp,"3");
mp_read_radix(sk,temp,10);
while (mp_cmp(sk,&nm1)==-1)
{
Ecc_points_mul(QX,QY,GX,GY,sk,A,P);//Q=sk*G
//printf("QX=%s\n",Check(QX));
r=CheckKey(QX,QY,sk,n,A,B,P);
if (r)
{
return;
}
else
mp_add_d(sk,1,sk);
}
mp_set(sk,0);
}
//检验密钥
bool CheckKey(mp_int*QX,mp_int*QY,mp_int*sk,mp_int*n,mp_int*A,mp_int*B,mp_int*P)
{
if (mp_cmp_d(QX,0)==0 && mp_cmp_d(QY,0)==0) //Q=O
{
return false;
}
if (mp_cmp_d(QX,0)==-1 || mp_cmp(QX,P)>=0) //QX<0||QX>=q
{
return false;
}
if (mp_cmp_d(QY,0)==-1 || mp_cmp(QY,P)>=0) //QY<0||QY>=q
{
return false;
}
mp_int tempx;mp_init(&tempx);
mp_int tempy;mp_init(&tempy);
mp_expt_d(QX,3,&tempx);
mp_mod(&tempx,P,&tempx);
/* d = a * b (