首页 > 技术文章 > 第十届蓝桥杯省赛-试题E: RSA 解密

GarrettWale 2020-06-22 15:57 原文

试题E: RSA 解密

这里涉及到很多数论的知识:质因子分解,扩展欧几里得算法,快速幂算法,利用快速乘算法求解快速幂(mod太大导致不能直接乘,而是需要使用加法来替代乘法)

另外还需要注意扩展欧几里得算法求解出来的乘法逆可能是负数,所以需要使用公式进行转换。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<fstream>

using namespace std;
typedef long long LL;
/*
首先生成两个质数p, q,令n = p * q,设d 与(p -1)*(q -1) 互质,则可
找到e 使得d * e 除(p-1)*(q -1) 的余数为1。
现在你知道公钥中n = 1001733993063167141, d = 212353,同时你截获了别人发送的密文C = 20190324,请问,原文是多少?
当收到密文C 时,可使用私钥解开,计算公式为X = C^e mod n。答案:579706994112328949 
*/
/*
p=891234941 q=1123984201
*/
//扩展欧几里得算法 
void exgcd(LL a,LL b,LL&d,LL& x,LL& y){//d=gcd(a,b)
	if(!b){
		d=a;
		x=1;
		y=0;
	}else{
		exgcd(b,a%b,d,y,x);
		y-=x*(a/b);
	}
}
//快速乘
LL quickMul(LL a,LL b,LL mod){
	LL ans=0;//这里初值为0 
	while(b){
		if(b&1)
			ans=(ans+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	return ans%mod;
} 
LL quickPower(LL a,LL b,LL mod){
	LL ans=1;//注意这里初值是1 
	while(b){
		if(b&1)
			ans=quickMul(ans,a,mod)%mod;
		a=quickMul(a,a,mod)%mod;
		b>>=1;
	}
	return ans%mod;
}
int main(){
	LL n=1001733993063167141;
	//分解质因数 
	for(LL i=2;i*i<=n;i++){
		while(n%i==0){
			//cout<<i<<" "<<n/i<<endl;//两个质数 
			n/=i;
		}
	}
	LL p=891234941,q=1123984201;
	LL mod=(p-1)*(q-1);
	LL d=212353;
	LL e,y,gcd;
	//d*e==1(%mod)
	//扩展欧几里得算法 
	exgcd(d,mod,gcd,e,y);
	e=(e%mod+mod)%mod;//这里是因为e可能为负数 
	//cout<<e<<endl;
	LL c=20190324;
	n=1001733993063167141;
	//X = C^e mod n
	LL x;
	//快速幂和快速乘相结合 
	cout<<quickPower(c,e,n)<<endl;
	return 0;
}

推荐阅读