……来自 @百度作业帮
RSA中,e*d=1(mod(p-1)(q-1))中为什么是mod(p-1)(q-1)而不是mod pq ?
答:
用a表示加密前的信息,b表示加密后的信息,c表示用另一对密钥解密后所得的信息,那么:
对明文加密后得b≡a^e mod(p*q);
然后再用另一对密钥解密b得c≡b^d≡(a^e)^d=a^(e*d) mod(p*q);
现在还是不能确定是否有a=c,即a^(e*d)≡ a mod(p*q)(解密后得信息与加密前的一样)
但是如果我们让e*d=1 mod(p-1)(q-1); 即 e*d = k(p-1)(q-1)+1;
那么c≡a^(e*d)=a^(k(p-1)(q-1)+1) ≡ a mod(p*q);
(根据欧拉定理:a^((p-1)(q-1))≡1 mod(p*q))
在限制0≤ a,c<p*q的情况下,a=c
如果a不与p*q互素,也有相同的结论.
//上面所说 就是在 e*d=1 mod(p-1)(q-1)时,使得 a^(e*d)≡ a mod(p*q)
//
下面是来自 @宫藏嘉辈 类似的证明,可能看起来更清晰些
http://www.cnblogs.com/zhtxwd/archive/2012/02/09/2344154.html
RSA定理证明:
定理:设p,q是不同的素数,n=pq记φ(n)=(p-1)(q-1),如果e,d是与φ(n)互素 的两个正整数(e,d<φ(n)),
并满足 ed≡1(mod φ(n)), 则对于每个整数x,都有x^ed≡x(mod n)。
分析:为了证明x^ed≡x(mod n),只要证明φ(n)是x^ed-x的因数即可。又因为n=pq,而p,q都是素数,
故只要证明p和q都是xed-x的因数即可,即
x^ed≡x(mod p) (1)
x^ed≡x(mod q) (2)
证明:证明式1,若p是x的因数则式1必然成立
若p不是x的因数,则由ed≡1(mod φ(n))得ed-1=k(p-1)(q-1),k为任意整数。
则x^ed=x^(k(p-1)(q-1)+1) = x * (x^(p-1))^k(q-1)
根据费马小定理因为x与p互素所以x^(p-1) ≡1(mod p)
所以x^ed≡x * 1^k(q-1) ≡x(mod p)
同理可证x^ed≡x(mod q)
例题:
题解来自 @芋智波佐助
http://blog.csdn.net/u011686226/article/details/38960211
URAL 1141. RSA Attack
题意:给你e n c 并且有m^e = c(mod n) 求 m
思路: RSA算法
过程大致是
1.发送的信息是m
2.随机选择两个质数 p和q, n = q*p, n的欧拉函数值φ(n)= (p-1)*(q-1)
3.选择一个与φ(n)互质的并且小于φ(n)的数e, 计算c = m^e(mod n)
4.发送c
5解密 求e的逆元d 逆元就是2个数乘一下在mod一个数等于1 这里就是e*d = 1(mod φ(n))
(求逆元用扩展欧几里德)
6.计算c^d(mod n) 就是m
下面是我自己写的:(其实还是套的模板QAQ)
//URAL 1141
//Time: 15MS
//Memory: 652 KB
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long int LL;
const int MAXN = 32010;
int phi[MAXN],prime[MAXN],cnt_p;
int flag_p[MAXN];
//线性欧拉函数
void getphi()
{
cnt_p = 0;
memset(flag_p,0,sizeof(flag_p)); //0为素数
flag_p[0] = 1;
flag_p[1] = 1;
phi[0] = 0;
phi[1] = 0;//???
for(int i=2; i<MAXN; ++i)
{//cout<<"xxx"<<endl;
if(!flag_p[i]) { prime[cnt_p++] = i; phi[i] = i-1; }
for(int j=0; j<cnt_p && i*prime[j]<MAXN; ++j)
{
flag_p[i*prime[j]] = 1;
if(!(i%prime[j])) { phi[i*prime[j]] = phi[i]*prime[j]; break;}
else phi[i*prime[j]] = phi[i]*(prime[j]-1); //若p为素数,则pih[p] = p-1;
}
}
return ;
}
//快速幂
LL quike_mod(LL a,LL b,LL M)
{
LL ans = 1;
while(b)
{
if(b&1)
{
ans = (ans*a)%M;
--b;
}
b = b/2;
a = ((a%M)*(a%M))%M;
}
return ans;
}
//扩展欧几里得
LL ex_gcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x = 1;
y = 0;
//return ;
return a;
}
//LL ans = ex_gcd(b,a%b,x,y);
LL ans = ex_gcd(b,a%b,x,y);
LL temp = x;
x = y;
y = temp - (a/b) * y;
return ans; ///ans是最大公约数
}
//求方程解,逆元等...
//方程: a*x + b*y = c
LL niyuan(LL a,LL b,LL c)
{
LL x,y;
LL gcd=ex_gcd(a,b,x,y);
if(c%gcd!=0) return -1;
x*=c/gcd;
b/=gcd;
if(b<0) b=-b;
LL ans=x%b;
if(ans<=0) ans+=b;
return ans;
}
int main()
{
//ss();
getphi(); ///因为 n=p*q, 且p,q都是素数;那么n的欧拉函数 = (p-1)*(q-1);
LL e,n,c;
int T;
scanf("%d",&T);
while(T--)
{
scanf("%I64d%I64d%I64d",&e,&n,&c);
//e关于对phi[n]取模的逆元
LL d = niyuan(e, phi[n], 1);
LL m = quike_mod(c, d, n);
printf("%lld\n",m);
}
return 0;
}