/********************************************************************/
/* */
/* MY_RSA PROGRAM(demo) */
/* Author:lixiongwei */
/* Time: 5/14/2006 Sun. */
/* Chang'an University Computer lab. */
/* WIN XP+(TC/Win_TC/VC++6.0) */
/* */
/********************************************************************/
#include "stdlib.h"
#include "stdio.h"
#include "math.h"
/*=========================variable area======================================*/
typedef struct rsa_temp
{
unsigned long int f;
unsigned long int n;
unsigned int e;
unsigned int d;
}rsa_pt; /*定义函数参数结构体*/
unsigned long int n;
unsigned long int f; /* f=(p-1)*(q-1),不参与加密解密运算 */
int e; /*公匙,n=p*q,gcd(e,f)=1*/
int d; /*私匙,e*d=1 (mod f),gcd(n,d)=1*/
unsigned int p,q; /*两个素数 */
unsigned long int s; /* 块长,满足2^s<=n的最大的s,即log2(n) */
const static g_PrimeTable[]=
{ 3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97 }; /*小素数表*/
const static int l_PrimeTable[]=
{2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,
107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,
223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,
337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,
457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,
593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,
719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,
857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,
997};
const static g_PrimeCount=sizeof(g_PrimeTable) / sizeof(int);
const static l_PrimeCount=sizeof(l_PrimeTable) / sizeof(int);
/*==========================function antetype==================================*/
void build_rsa_param(unsigned int x, unsigned int y, rsa_pt *my_temp);
int gcd(unsigned long int,unsigned long int);
unsigned power(unsigned,unsigned,unsigned long);
void convert_16_to_8(unsigned int *a,unsigned char *b);
void convert_8_to_16(unsigned char *b,unsigned int *a);
void coder(unsigned char *original_str, unsigned int *encrypted_data,
unsigned int *decrypted_data) ;
void decoder(unsigned char *original_str, unsigned int *encrypted_data,
unsigned int *decrypted_data) ;
int menu(); /* 菜单函数 */
void en_de_code(); /*菜单一:RSA 加密解密函数*/
void explay_rsa(); /*菜单二:演示 p,q 的计算函数*/
void display_rsa();/*菜单三:自动显示一组PQNFED值的函数*/
int prime(int n); /* 判断素数 */
unsigned int random_prime(char bits); /* 产生素数 */
long int rabin_miller(unsigned long int n, unsigned long int loop);/* 素数测试函数*/
long int RabinMillerKnl(unsigned long int n);/* 素数测试函数 */
unsigned long int EuclidGcd(unsigned long int p, unsigned long int q);
unsigned long int Euclid(unsigned long int a, unsigned long int b);
/*=================================MAIN=======================================*/
main()
{ while(1)
while(1)
{
switch(menu())
{
case 1: en_de_code();
break;
case 2: explay_rsa();
break;
case 3: display_rsa();
case 4: exit(-1);
default:
printf("Enter error,please again!");
fflush(stdin);
getchar();
}/* switch end */
}/* while end */
getch();
}
/*------------------------------------------*/
int menu() /* 主菜单 */
{
int ch;
system("cls");
fflush(stdin);
printf("/n================MY_RSA PROGRAM<demo>================/n/n");
printf("1.Encryption and Decryption data./n");
printf("2.Explain RSA(input P,Q return N,F,E,D etc.)/n");
printf("3.Display a group of(P,Q,N,F,E,D)./n");
printf("4.Quit RSA program./n");
printf("/nPlease enter your choice(1,2,3,4):/n");
scanf("%d",&ch);
return ch;
}
/*=============================function definition=============================*/
void en_de_code()
{
int i;
unsigned char *str;
unsigned char first_data[100];/*保存用户输入数据*/
unsigned int code_data[100], decode_data[100];
rsa_pt *temp1,temp;
temp1=&temp;
system("cls");
build_rsa_param( random_prime(16),random_prime(16) ,temp1 );/* 初始化过程,自动产生 n,f,e,d,p,q,s*/
printf("/n/n<< n=%lu, f=%lu,e=%d, d=%d>>/n/n",temp1->n,temp1->f,temp1->e,temp1->d);
/*调用 random_prime 生成2个素数*/
str= (unsigned char *)first_data;
printf("/nPlease enter your text to code:/n");
scanf("%s",str);
printf("******************************************************/n");
coder(str, code_data, decode_data) ;
printf("/nAfter encrypt data is:/n%s", str);
printf("/nAfter encrypt data<hex> is:/n");
for(i=0; i<strlen(str); i++)
printf("%0x ",str[i] );
decoder(str, code_data, decode_data) ;
printf("/n/n/nAfter decry data is:/n%s",str);
printf("/nAfter decrypt data<hex> is:/n");
for(i=0; i<strlen(str); i++)
printf("%0x ",str[i] );
printf("/n/n/nOperation is over,press any key restart.../n");
printf("*****************************************************/n");
printf("/n%c,%c",power(23,e,n),power(23,d,n));
getch();
}
/*------------------------------------------*/
void explay_rsa() /* 用来演示RSA算法..............*/
{
int i=0,j=0;
unsigned my_p,my_q;
rsa_pt *temp2,temp;
temp2=&temp;
system("cls");
while(1)
{
i++;
printf("/nPlease enter two prime (my_p and my_q):/n");
scanf("%d %d",&my_p,&my_q);
if(prime(my_p) && prime(my_q))
{
printf("Very good,your enter two numbers is both prime number./n");
printf("Now program is compute n,f,e,d etc.please wait.... /n");
while(j<=5)
{
build_rsa_param(my_p, my_q, temp2 ); /* 初始化过程,自动产生 n,f,e,d,s*/
printf("/n/n<< n=%lu, f=%lu,e=%d, d=%d>>/n/n",temp2->n,temp2->f,temp2->e,temp2->d);
j++;
}
getch();
break;
}
else
{
printf("p or q is not a prime number,please again./n");
if(i>=3)
break;
}
} /* while end */
}
void display_rsa()
{
int i=0,flag=0;
unsigned my_p=3,my_q=3;
rsa_pt *temp3,temp;
temp3=&temp;
system("cls");
printf("Your want to display (P,Q)<100 or (P,Q)<1000?/n");
printf("Please enter 100/1000: ");
scanf("%d",&flag);
while(1)
{
i++;
if(flag==100)
{
my_p=g_PrimeTable[random(g_PrimeCount)];
my_q=g_PrimeTable[random(g_PrimeCount)];
}
else
{
my_p=l_PrimeTable[random(l_PrimeCount)];
my_q=l_PrimeTable[random(l_PrimeCount)];
}
if(my_p==my_q) continue;
printf("Now program is compute n,f,e,d etc.please wait.... /n");
build_rsa_param(my_p, my_q, temp3 ); /* 初始化过程,自动产生 n,f,e,d,s*/
printf("/n/n<< n=%lu, f=%lu,e=%d, d=%d>>/n/n",temp3->n,temp3->f,temp3->e,temp3->d);
getch();
if(i>=100) break;
} /* while end */
}
/*------------------------------------------*/
void build_rsa_param(unsigned int x, unsigned int y, rsa_pt *my_temp) /*产生公钥*/
{
unsigned int t;
/*随机生成两个素数*/
/* p=random_prime(16);
q=random_prime(16);
*/
p=x; q=y;
n=p * q;
f=(p - 1) * (q - 1);
do
{
e=random(65536); /* 小于2^16,65536=2^16 */
e|=1; /* 保证最低位是1,即保证是奇数,因f一定是偶数,要互素,只能是奇数 */
}while(EuclidGcd(e, f) != 1);
d=Euclid(e, f);
s=0; /* s=log2(n) */
t=n >> 1;
while(t)
{
s++;
t>>=1;
}
printf("/n/n<<----------------p=%u, q=%u----------------->>",p,q);
my_temp->n=n;
my_temp->f=f;
my_temp->d=d;
my_temp->e=e;
}
/*------------------------------------------*/
/* 随机生成一个bits位(二进制位)的素数,最多32位 */
unsigned int random_prime(char bits)
{
unsigned int base;
do
{
base= (unsigned)1 << (bits - 1); /*保证最高位是1*/
base+=random(base); /*再加上一个随机数*/
base|=1; /*保证最低位是1,即保证是奇数*/
} while(!rabin_miller(base, 30)); /*进行拉宾-米勒测试30次*/
return base; /*全部通过认为是素数*/
}
/*------------------------------------------*/
unsigned long int EuclidGcd(unsigned long int p, unsigned long int q)
{
unsigned long int a=p > q ? p : q;
unsigned long int b=p < q ? p : q;
unsigned long int t;
if(p == q)
{
return p; /* 两数相等,最大公约数就是本身 */
}
else
{
while(b) /* 辗转相除法,gcd(a,b)=gcd(b,a-qb) */
{
a=a % b;
t=a;
a=b;
b=t;
}
return a;
}
}
/*------------------------------------------*/
/* 已知a、b,求x,满足a*x =1 (mod b) 相当于求解a*x-b*y=1的最小整数解 */
unsigned long int Euclid(unsigned long int a, unsigned long int b)
{
unsigned long int m, e, i, j, x, y;
long int xx, yy;
m=b;
e=a;
x=0;
y=1;
xx=1;
yy=1;
while(e)
{
i=m / e;
j=m % e;
m=e;
e=j;
j=y;
y*=i;
if(xx == yy)
{
if(x > y)
{
y=x - y;
}
else
{
y-=x;
yy=0;
}
}
else
{
y+=x;
xx=1 - xx;
yy=1 - yy;
}
x=j;
}
if(xx == 0)
{
x=b - x;
}
return x;
}
/*------------------------------------------*/
void convert_8_to_16(unsigned char *b,unsigned int *a)
{
int i;
for(i=0;i<100;i++)
a[i]=b[2*i]*256+b[2*i+1];
/* text_16[i]=text_8[2*i]*256+text_8[2*i+1];*/
}
/*------------------------------------------*/
void convert_16_to_8(unsigned int *a,unsigned char *b)
{
int i=0,flag=0;
unsigned int temp;
while(i<200&&flag<100)
{
temp=a[flag]/256;
b[i]=temp;
b[i+1]=a[flag]%256;
i+=2;
flag++;
}
}
/*------------------------------------------*/
void coder(unsigned char *original_str, unsigned int *encrypted_data, unsigned int *decrypted_data) /* 对所给数据加密*/
{
int i;
i=0;
convert_8_to_16(original_str, decrypted_data);
while(decrypted_data[i]!=0)
{
encrypted_data[i]=power(decrypted_data[i],e,n);
i++;
}
convert_16_to_8(encrypted_data,original_str);
}
/*------------------------------------------*/
void decoder(unsigned char *original_str, unsigned int *encrypted_data, unsigned int *decrypted_data) /* 对所给数据解密*/
{
int i;
i=0;
while(encrypted_data[i]!=0)
{
decrypted_data[i]=power(encrypted_data[i],d,n);
i++;
}
convert_16_to_8(decrypted_data,original_str);
}
/*------------------------------------------*/
unsigned power(unsigned a,unsigned b,unsigned long c) /*The power,you can get a,b,c*/
{
unsigned long z=1,t;
for(t=a;b>0;b>>=1)
{
if(b%2==1)z=(z*t)%c;
t=(t*t)%c;
}
return z;
}
/*------------------------------------------*/
/* Rabin-Miller素数测试,通过测试返回1,否则
返回0。n是待测素数。注意:通过测试并不一定就
是素数,非素数通过测试的概率是1/4 */
long int RabinMillerKnl(unsigned long int n)
{
unsigned long int b, m, j, v, i;
m=n - 1;
j=0; /* 0、先计算出m、j,使得n-1=m*2^j,其中m是正奇数,j是非负整数*/
while(!(m & 1))
{
++j;
m>>=1;
} /*1、随机取一个b,2<=b<n-1*/
b=2 + random(n - 3); /*2、计算v=b^m mod n*/
v=power(b, m, n); /*3、如果v==1,通过测试*/
if(v == 1)
{
return 1;
} /*4、令i=1 */
i=1; /*5、如果v=n-1,通过测试*/
while(v != n - 1)
{
/*6、如果i==l,非素数,结束*/
if(i == j)
{
return 0;
} /*7、v=v^2 mod n,i=i+1*/
v=power(v, 2, n);
++i; /*8、循环到5*/
} return 1;
}
/*------------------------------------------*/
/*Rabin-Miller素数测试,循环调用核心loop次全部通过返回1,否则返回0 */
long int rabin_miller(unsigned long int n, unsigned long int loop)
{
/* 先用小素数筛选一次,提高效率 */
long int i;
for(i=0; i < g_PrimeCount; i++)
{
if( n%g_PrimeTable[i] == 0) /* 这里修改 */
{
return 0;
}
}
/*循环调用Rabin-Miller测试loop次,使得非素数通过测试的概率降为(1/4)^loop*/
for(i=0; i < loop; i++)
{
if(!RabinMillerKnl(n))
{
return 0;
}
} return 1;
}
/*------------------------------------------*/
int prime(int n) /* 判断素数 */
{
int i,k;
k=sqrt(n);
for(i=2;i<=k;i++)
if(n%i==0) break;
if(i>k) return 1 ;
else return 0;
}
/*===================================================================*/