#include<stdio.h>
#include<conio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#define TIMES 50
#define MAX 100 //素数的范围
#define MIN 1
long Suiji() //随机数生成基本函数
{
long i;
srand((unsigned)time(NULL));
i = rand()%MAX+MIN;
return i;
}
int Square_and_Multiply(long a,long m,long n)
{
//m change into bits b……k位(指针数组)bits
long d,bits[100],i,k; //k位
d=1;
i=0;
while(1) //将m转换为二进制,方法为除2取余
{
bits[i]=m%2;
if(m/2==0)break;
m=m/2;
i++;
}
k=i;
for(i=k;i>=0;i--) //计算am mod n
{
d=d*d%n;
if(bits[i]==1)
d=(d*a)%n;
}
return d;
}
int Miller_Rabin(long n) //Miller_Rabin素数测试
//通过测试返回1,否则返回0。n是待测素数,大于3的奇数。
{
long a,i,k,m,t;
int b;
//n-1=2^k m,m为一个奇数,在{2,……,n-1}中随机地选取一个整数a;
t=n-1;
k=0;
while(t%2==0) //算出 k
{ t=t/2;
k++;
}
m=t; //计算m m=(n-1)/pow(2,k)
a=Suiji()%(n-3)+2; //随机取一个a,在{2,n-1}范围内 此方法OK
b=Square_and_Multiply(a,m,n);
if(b==1)
return 1;//n是素数
for(i=0;i<k;i++)
{
if(b==n-1)
return 1;
else
b=b*b%n;
}
return 0;
}
int BeforeMR(long n)////保证n是大于3的奇数才进行 素数测试
{
int flag;
while(n==3||n==2) return 1;
while(n==1) return 0;
while(n%2==0) return 0;
flag=Miller_Rabin(n);//大于3的奇数才进行 素数测试
return flag;
}
long MakeNumber()//随机生成大素数
{
long p,t;
int i,j;
start:
//sleep(1);
p=Suiji(); //随机产生一个数
if(p%2==0)p=p+1; //确保产生的数为奇数
for(i=0;i<TIMES;i++) //素数检验TIMES次
{
t=p;
j=BeforeMR(t);
if(j==0)
{ printf("\t%ld ",t);
goto start;
}
}
return p;
}
long Make_e(long x) //生成公钥(e,n)中的e
{
long e,m,n,r;
srand((unsigned)time(NULL));
start:
e=rand()%x+1; //随机产生一个数e,在1到x之间
m=x;
n=e;
while((r=m%n)!=0) //判断e是否和n2互为素数
{
m=n;n=r;
}
if(n!=1) //如果不是,返回在重新产生e
{ goto start;
}
return e;
}
long Make_d(long e,long x) //生成私钥d
{
long d=1;
while( (e*d)% x !=1) //d符合的条件为d=e^(-1) mod x
d++;
return d;
}
void Encrypt(long ptext) //加密
{
long p,q,n,x,e,d;
long ctext;
p=MakeNumber();//生成p
//sleep(1);
again:
q=MakeNumber();//生成q
if(q==p) { goto again;}
n=p*q;
x=(p-1)*(q-1);
e=Make_e(x);////产生公钥e
d=Make_d(e,x); //产生私钥d
printf("\np = %ld ,q = %ld ",p,q);
printf("\npublic key: e = %ld n = %ld ",e,n);
printf("\t private key: d = %ld ",d);
ctext=Square_and_Multiply(ptext,e,n);//加密,密文=ptext^e mod n
if(ctext<0) printf("Erro!Can't work out the result!Please do again!\n");//溢出提示处理
else printf("\nThe ciphertext is: %ld ",ctext);
}
void Decrypt(long ctext) //解密
{
long n,d,ptext;
printf("Please input public key : n ="); //输入公钥n
scanf("%ld",&n);
printf("please input private key: d =");//输入私钥
scanf("%ld",&d);
ptext=Square_and_Multiply(ctext,d,n);//解密,明文=ctext ^d mod n
printf("The plaintext: %ld ",ptext);
}
void main()
{
int i;
long ptext,ctext;
system("cls");
printf("\t\tR S A");
start:
printf("\n1.Encryption.\n2.Decryption.\n0:Exit.\nPlease choose:");
scanf("%d",&i);
if(i!=0&&i!=1&&i!=2)
{
printf("Your choice isn't offered!Please choose again!\n");
goto start;
}
if(i==1)
{
printf("\nPlease input the plaintext(only number):");
scanf("%ld",&ptext);
Encrypt(ptext);
goto start;
}
if(i==2)
{
printf("\nPlease input the ciphertext(only number):");
scanf("%ld",&ctext);
Decrypt(ctext);
goto start;
}
if(i==0){ exit(0);goto start;}
}