www.pudn.com > VC++RSA.rar > RSAUpper.cpp
// RSAUpper.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define TRUE 1
#define FALSE 0
#define VLONG unsigned long
//参考书:《计算机密码学》(第二版)卢开澄 清华大学出版社
//模幂算法,快速计算:x^r(mod p),p76
VLONG MONmod(VLONG x,VLONG r,VLONG p)
{
VLONG a,b,c;
a=x;
b=r;
c=1;
while (b!=0)
{
if ((b&0x01)==0)
{
b=b/2;
a=(a*a)%p;
}
else
{
b=b-1;
c=(a*c)%p;
}
}
return c;
}
/*
* Rabin-Miller
* 这是个很容易且广泛使用的简单算法,它基于Gary Miller的部分象法,
* 有Michael Rabin发展。事实上,这是在NIST的DSS建议中推荐的算法的一个简化版。
* 首先选择一个代测的随机数p,计算b,b是2整除p-1的次数。然后计算m,使得n=1+(2^b)m。
* (1) 选择一个小于p的随机数a。
* (2) 设j=0且z=a^m mod p
* (3) 如果z=1或z=p-1,那麽p通过测试,可能使素数
* (4) 如果j>0且z=1, 那麽p不是素数
* (5) 设j=j+1。如果jp-1,设z=z^2 mod p,然后回到(4)。
* 如果z=p-1,那麽p通过测试,可能为素数。
* (6) 如果j=b 且z<>p-1,不是素数
* 这个测试较前一个速度快。数a被当成证据的概率为75%。这意味着当迭代次数为t时,它产生一个假的素数所花
* 费的时间不超过1/4^t。实际上,对大多数随机数,几乎99.99%肯定a是证据。
* 实际考虑:
* 在实际算法,产生素数是很快的。
* (1) 产生一个n-位的随机数p
* (2) 设高位和低位为1(设高位是为了保证位数,设低位是为了保证位奇数)
* (3) 检查以确保p不能被任何小素数整除:如3,5,7,11等等。有效的方法
* 是测试小于2000的素数。使用字轮方法更快
* (4) 对某随机数a运行Rabin-Miller检测,如果p通过,则另外产生一个随机
* 数a,在测试。选取较小的a值,以保证速度。做5次 Rabin-Miller测试如
* 果p在其中失败,从新产生p,再测试。
*/
//参考书:《计算机密码学》(第二版)卢开澄 清华大学出版社
//模幂算法,素数的米勒-勒宾(MIller-Rabin)概率测试法,p151
//输入:被 b要检测的数字,n素数产生的范围满足:(2<=b=(n-1))) return (false);
V=MONmod(b,m,n);
if (V==1) return (true);
i=1;
do
{
if (V==(n-1)) return (true);
if (i==l) return (false);
V=MONmod(V,2,n);
i++;
}
while (1);
return(false);
}
//参考书:《计算机密码学》(第二版)卢开澄 清华大学出版社
//求gcd{n1,n2}的快速算法,快速计算:gcd{n1,n2}=an1+bn2,p132
VLONG gcd(VLONG /*mod*/ n1,VLONG n2)
{
VLONG c;
VLONG t;
if ((n1<0) || (n2<=0)) return 0;
//s1
c=0;
//s2
while ((n1%2==0)&&(n2%2==0))
{
n1=n1/2;
n2=n2/2;
c++;
}
//s3
if (n2%2==0)
{
t=n1;
n1=n2;
n2=t;
}
do
{
//s4
while (n1%2==0)
{
n1=n1/2;
}
//s5
if ((long)(n1-n2)<0)
{
t=n1;
n1=n2;
n2=t;
}
//s6
n1=(n1-n2)/2;
}
while (n1!=0);
return (n2<PHI)
{
while (e % PHI != 0)
{
temp= e % PHI;
e =PHI;
PHI = temp;
}
great = PHI;
}
else
{
while (PHI % e != 0)
{
a = PHI % e;
PHI = e;
e = a;
}
great = e;
}
return(great);
}
VLONG getE( VLONG PHI)
{
VLONG great=0, e=2;
while (great!=1)
{
e=e+1;
great = gcd(e,PHI);
}
return(e);
}
void get_prime( VLONG *val)
{
#define NO_PRIMES 39
VLONG primes[NO_PRIMES]={3,5,7,11,13,
17,19,23,29,31,
37,41,43,53,59,
61,67,71,101,103,97,
107,109,113,127,131,
137,139,149,151,157,
163,167,173,179,181,
191,193,197};
VLONG prime,i;
do
{
prime=FALSE;
printf("Enter a prime number >> ");
scanf("%ld",val);
for (i=0;i> ");
scanf("%ld",&m);
printf("a=%ld b=%ld n=%ld PHI=%ld\n",a,b,n,PHI);
//模幂算法,快速计算:x^r(mod p),p76
//VLONG MONmod(VLONG x,VLONG r,VLONG p)
c=(VLONG)pow(m,e) % n; /* note, this may overflow with large numbers */
//c=MONmod(5,173,323);
//c=MONmod(5,173,323);
c=MONmod(m,e,n);
/* when e is relatively large */
printf("encrypt Message is %ld \n",c);
printf("e=%ld d=%ld c=%ld\n",e,d,c);
m=decrypt(c,n,d); /* this function required as c to */
/*the power of d causes an overflow */
printf("decrypt Message is %ld \n",m);
scanf("");
return(0);
}