资料出处:http://www.cnblogs.com/louzhang/archive/2012/04/29/2476498.html
程序出现了BUG
在计算幂取模的时候出现了错误
其实最重要的是私钥d可能会是负数,我并没有取整数的模(一直错在这,我以为可以。。。。)
其实此次学习最重要的是发现了-1右移等于-1吧。。。
代码我就直接替换掉新的了。。。
花了几天的时间终于搞定了NSGA-II,周三晚开完会讨论之后无误就来发表
今晚烦燥,就来复习信安基础了,做了个简单的RSA
只能计算Int范围内的,即p,q的选取在int范围内而且p*q不能超过int
写了也算一个学习经历吧,就到这里记录一下
代码里Miller_Robin是不需要的,只是写一下
Miller_Robin和Prime_Linear函数都是直接贴模板的,稍微作了点改动吧~
其实一看就知道,没注释的就是我写的,注释的就不是我的(太懒了,不喜欢写注释,反正这个写着自己看Orz)
其实为了自己看的懂,还做了“无用功”,有些输入的提示
下面是结果
p=11,q=17
e=7 --->通过扩展欧几里得求出 d=23
明文M=88 --->C=11
密文C=11 --->M=88
如果哪位对弱菜我的小程序感兴趣,测试之后发现有BUG还望提出啊Orz.........................
下面就上代码了~~~~
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
const int maxn = 10000000;
bool IsNotPrime[maxn]; // 判断是否为素数.
int PrimeList[maxn]; // 素数列表.
int PrimeNum;
void Prime_Linear(void)
{ // 速度比朴素筛法快2倍以上,该筛法进行稍微修改即可用于求欧拉函数Phi[].
int i, j;
memset(IsNotPrime, 0, sizeof(IsNotPrime)); // 初始赋值所有数都是素数.
IsNotPrime[1] = 1; IsNotPrime[0] = 1; // 0和1不是素数.
PrimeList[0]=2;
for (i = 4; i < maxn; i += 2) IsNotPrime[i] = 1; // 除2以外的所有偶数都不是素数.
PrimeNum = 1;
for (i = 3; i < maxn; i += 2)
{
if (!IsNotPrime[i])
{ // 如果是素数则加入素数列表.
PrimeList[PrimeNum++] = i;
}
// 注意:这里与朴素筛法不同,即使合数也要进行筛.
// 因为这里素数只筛它的素数倍,那么有些合数就可能没被筛掉.
// 而这些合数就需要合数来晒,而且只要筛到它的最小质因子倍即可(想想为什么?).
for (j = 0; j < PrimeNum && i * PrimeList[j] < maxn; j++)
{
IsNotPrime[i * PrimeList[j]] = 1;
if (i % PrimeList[j] == 0)
{ // 说明PrimeList[j]是i的最小质因子,即i * PrimeList[j]的最小质因子,则跳出.
break;
}
}
}
}
int Modular_Exponent(int a, int b, int MOD)
{ // a ^ b mod MOD.
int temp(1);
int aa(a);
while (b)
{
if (b & 1) temp = 1LL * temp * aa % MOD;
aa = 1LL * aa * aa % MOD;
b >>= 1;
}
return temp;
}
// Carmicheal number: 561,41041,825265,321197185
bool Miller_Rabin(int n, int time = 20)
{ // 如果是素数,则返回1,否则返回0.
if (n == 1 || (n != 2 && !(n % 2)) || (n != 3 && !(n % 3))
|| (n != 5 && !(n % 5)) || (n != 7 && !(n % 7)))
return 0;
while (time--)
{
if (Modular_Exponent(((rand() & 0x7fff << 16) +
rand() & 0x7fff + rand() & 0x7fff) % (n-1) + 1, n - 1, n) != 1)
return 0;
}
return 1;
}
void ext_gcd(int a,int b,int&x,int&y){
if(!b){
x=1,y=0;
return;
}
ext_gcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int init(int p,int q,int &e){
//Prime_Linear();
int eular_n=(p-1)*(q-1);
puts("please input a prime nunber as your public key");
while(true){
scanf("%d",&e);
if(IsNotPrime[e] || gcd(e,eular_n)!=1){
puts("wrong input,please input again~");
continue;
}
break;
}
int d,y;
ext_gcd(e,eular_n,d,y);
return (d+eular_n)%eular_n;
}
void exponent(int a,const int e,int n,int select){
int ret=1;
int b=e;
for(;b;b=(b==-1)?0:(b>>1),a=(int)((long long)a)*a%n)
//for(;b;b/=2,a=(int)((long long)a)*a%n)
if(b&1)
ret=(int)((long long)ret)*a%n;
switch(select){
case 1:printf("your ciphertext is %d\n",ret%n);break;
case 2:printf("your plaintext is %d\n",ret%n);
}
}
int main(){
Prime_Linear();//初始化,素数打表
//for(int i=0;i<10;i++)printf("%d\n",PrimeList[i]);
//for(int i=0;i<10;i++)printf("%d\n",IsNotPrime[i]);
int p,q,e;
loop:
puts("please input two prime number");
scanf("%d%d",&p,&q);
//if(!Miller_Rabin(p)||!Miller_Rabin(q) ||
if(IsNotPrime[p] || IsNotPrime[q] ||
(long long)p+(long long)q>(~0U>>1)){
puts("your inputs is wrong,please input again~");
goto loop;
}
int d=init(p,q,e);
//printf("%d\n",d);
int select;
while(true){
puts("please select it");
puts("1: encryption");
puts("2: decryption");
while(true){
scanf("%d",&select);
if(select!=1 && select!=2){
puts("wrong input,please input again~");
continue;
}
break;
}
//puts("yes");
switch(select){
case 1:puts("please input a message");break;
case 2:puts("please input a cyphertext");
}
int m;
scanf("%d",&m);
switch(select){
case 1:exponent(m,e,p*q,select);break;
case 2:exponent(m,d,p*q,select);
}
}
}