RSA算法基于一个事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。


具体流程是:


RSA加密_ios



hdu 1211 RSA


​http://acm.hdu.edu.cn/showproblem.php?pid=1211​


按照题目所讲的步骤来就行。



#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
void exgcd(LL a,LL b,LL &x,LL &y){
if(b==0){
x=1; y=0;
return ;
}
exgcd(b,a%b,x,y);
LL t=x;
x=y;
y=t-a/b*y;
}
LL power(LL a,LL p,LL m){
LL ans=1;
while(p){
if(p&1) ans=ans*a%m;
a=a*a%m;
p>>=1;
}
return ans;
}
int main()
{
LL p,q,e,l;
LL c;
while(~scanf("%lld%lld%lld%lld",&p,&q,&e,&l)){
LL n=p*q;
LL fn=(p-1)*(q-1);
LL d,y,m;
exgcd(e,fn,d,y);
d=(d%fn+fn)%fn;
while(l--){
scanf("%lld",&c);
m=power(c,d,n);
printf("%c",m);
}
printf("\n");
}
return 0;
}


POJ 2447 RSA 



​http://poj.org/problem?id=2447​



大意:两个素数P,Q  N=P*Q


T=(P-1)(Q-1)   


0<E<N    
(E,T)=1


≡ 1 (mod T)


加密过程:C = (M ^ E) mod N


解密过程: M = (C ^ D) mod N


求出M   (0 < C < N, 0 < E < N, 0 < N < 2 ^ 62). 



因为 (E,T)=1互质,由欧拉定理可以得到E模T的逆元。剩余的工作就是套用原理公式。



#include <iostream>
#include <cstdio>
#include <stdlib.h>
using namespace std;
typedef long long LL;
const int N=5;
LL fac[N],num[N];
int cnt;
LL gcd(LL a,LL b){
return b==0?a:gcd(b,a%b);
}
LL multi(LL a,LL b,LL m){
LL ans=0;
while(b){
if(b&1) ans=(ans+a)%m;
a=(a+a)%m;
b>>=1;
}
return ans;
}
LL quick_mod(LL a,LL p,LL m){
LL ans=1;
while(p){
if(p&1) ans=multi(ans,a,m);
a=multi(a,a,m);
p>>=1;
}
return ans;
}
LL Pollard_rho(LL n,LL c){
LL x,y,k=2,i=1;
x=rand()%(n-1)+1;
y=x;
while(1>0){
i++;
x=(multi(x,x,n)+c)%n;
LL d=gcd((y-x+n)%n,n);
if(1<d&&d<n) return d;
if(y==x) return n; // 出现循环
if(i==k) {
y=x;
k<<=1; //x 比y多跑一圈
}
}
}
bool Miller_rabin(LL p){
if(p==2) return 1;
if(p<2 || (p&1)==0) return 0;
LL m=p-1;
int sum=0;
while((m&1)==0){
m>>=1;
sum++;
}
for(int i=0;i<10;i++){
LL a=rand()%(p-1)+1;
LL x=quick_mod(a,m,p);
LL g=0;
for(int j=0;j<sum;j++){
g=multi(x,x,p);
if(g==1&&x!=1&&x!=p-1) return 0;
x=g;
}
if(g!=1) return 0;
}
return 1;
}

void sfind(LL n,LL c){
if(n==1) return ;
if(Miller_rabin(n)){
fac[cnt++]=n;
return ;
}
LL p=n;
while(p>=n) p=Pollard_rho(p,c--); //循环避免没找到
sfind(p,c);
sfind(n/p,c);
}
LL phi(LL x){
LL ans=x;
for(LL i=2;i*i<=x;i++){
if(x%i==0){
ans=ans-ans/i;
while(x%i==0) x/=i;
}
}
if(x>1) ans=ans-ans/x;
return ans;
}
int main()
{
LL c,e,n;
while(~scanf("%lld %lld %lld",&c,&e,&n)){
cnt=0;
sfind(n,120);
LL t=(fac[0]-1)*(fac[1]-1);
LL D=quick_mod(e,phi(t)-1,t);
printf("%lld\n",quick_mod(c,D,n));
}
return 0;
}