第十屆藍橋杯省賽-試題E: RSA 解密


試題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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM