rsa加密算法_源代码000_c__实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
RSA算法
1978年就出现了这种算法,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。但RSA的安全性一直未能得到理论上的证明。
RSA的安全性依赖于大数难于分解这一特点。公钥和私钥都是两个大素数(大于100个十进制位)的函数。据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积。
密钥对的产生。选择两个大素数,p 和q 。计算:n = p * q 然后随机选择加密密钥e,要求e 和( p - 1 ) * ( q - 1 )互质。最后,利用Euclid 算法计算解密密钥d, 满足e * d = 1 ( mod ( p - 1 ) * ( q - 1 ) )其中n和d也要互质。数e和n是公钥,d是私钥。两个素数p和q 不再需要,应该丢弃,不要让任何人知道。加密信息m(二进制表示)时,首先把m分成等长数据块m1 ,m2,..., mi ,块长s,其中2^s <= n, s 尽可能的大。对应的密文是:ci = mi^e ( mod n ) ( a ) 解密时作如下计算:mi = ci^d ( mod n ) ( b )
RSA 可用于数字签名,方案是用( a ) 式签名,( b )式验证。具体操作时考虑到安全性和m信息量较大等因素,一般是先作HASH 运算。RSA 的安全性。RSA的安全性依赖于大数分解,但是否等同于大数分解一直未能得到理论上的证明,因为没有证明破解RSA 就一定需要作大数分解。假设存在一种无须分解大数的算法,那它肯定可以修改成为大数分解算法。目前,RSA的一些变种算法已被证明等价于大数分解。不管怎样,分解n是最显然的攻击方法。现在,人们已能分解140多个十进制位的大素数。因此,模数n必须选大一些,因具体适用情况而定。
由于进行的都是大数计算,使得RSA最快的情况也比DES慢上100倍,无论是软件还是硬件实现。速度一直是RSA的缺陷。一般来说只用于少量数据加密。
*/
#include
#include
#include
typedef struct RSA_PARAM_Tag
{ unsigned __int64 p, q; //两个素数,不参与加密解密运算
unsigned __int64 f; //f=(p-1)*(q-1),不参与加密解密运算
unsigned __int64 n, e; //公匙,n=p*q,gcd(e,f)=1
unsigned __int64 d; //私匙,e*d=1 (mod f),gcd(n,d)=1
unsigned __int64 s; //块长,满足2^s<=n的最大的s,即log2(n)
} RSA_PARAM;//小素数表
const static long 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 long g_PrimeCount=sizeof(g_PrimeTable) / sizeof(long);const unsigned __int64 multiplier=12747293821;
const unsigned __int64 adder=1343545677842234541;//随机数类
class RandNumber{ private:
unsigned __int64 randSeed;
public:
RandNumber(unsigned __int64 s=0);
unsigned __int64 Random(unsigned __int64 n); };
RandNumber::RandNumber(unsigned __int64 s)
{ if(!s)
{ randSeed= (unsigned __int64)time(NULL); }
else
{ randSeed=s; } }
unsigned __int64 RandNumber::Random(unsigned __int64 n)
{ randSeed=multiplier * randSeed + adder;
return randSeed % n;
}static RandNumber g_Rnd;/* 模乘运算,返回值x=a*b mod n */
inline unsigned __int64 MulMod(unsigned __int64 a, unsigned __int64 b, unsigned __int64 n) { return a * b % n;
} /* 模幂运算,返回值x=base^pow mod n */
unsigned __int64 PowMod(unsigned __int64 &base, unsigned __int64 &pow, unsigned __int64 &n)
{ unsigned __int64 a=base, b=pow, c=1;
while(b)
{ while(!(b & 1))
{
b>>=1; //a=a * a % n; //函数看起来可以处理64位的整数,但由于这里a*a 在a>=2^32时已经造成了溢出,因此实际处理范围没有64位
a=MulMod(a, a, n);
} b--; //c=a * c % n; //这里也会溢出,若把64位整数拆为两个32位整数不知是否可以解决这个问题。
c=MulMod(a, c, n);
} return c;
}/* Rabin-Miller素数测试,通过测试返回1,否则返回0。n是待测素数。注意:通过测试并不一定就是素数,非素数通过测试的概率是1/4 */
long RabinMillerKnl(unsigned __int64 &n)
{ unsigned __int64 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 b=2 + g_Rnd.Random(n - 3); //2、计算v=b^m mod n v=PowMod(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