首先先解決這樣一個問題,b和m已知求滿足下面條件的x,
這個問題若是沒有限制條件的話會變得很棘手,那麼假設條件變得更強讓gcd(b,m)=1;便會想到利用歐拉函數求出 ,之後解下面的不定方程。
- =1
假設gcd(k, )=1,那麼一定存在一組非負解x=a,y=b;使得
則有
則可以計算出 ,這樣便給出了計算模m的k次冪的方法。
於是問題就轉化成了如何求 - =1,以及 前者十分好求利用擴展歐幾里得算法可以快速求出
void _exgcd(ll a,ll b,ll &x,ll &y)
{if (!b){x=1;y=0;return;}_exgcd(b,a%b,y,x);y-=x*(a/b);}
後者則要用到求 的公式:
(p爲m的因子)
m很小時對於m的因數分解是非常容易的,但是一旦m很大時便非常困難
RSA加密的辦法就是利用以上思路,取兩個質數p q並求出 再取一個k與 互素,則可以則對 任意x 都可以求出一個對應的b來,b就是加密後的密文。
例如:取質數p=9973,q=10039 則m=p q=100118947 (p-1)(q-1)=100098936
在取k=364213;則構成以套加密體系:
假設密文M爲:GBDWG(對應關係爲A=30,B=31……Z=55)
M=3631335236;將密文分爲小於q長度的幾部分,分別爲 36313352 和36
則有
b=66250740與35570701就是密文
解密的過程就是求
下面是實現的代碼(寫的很挫)。。。
加密:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
using namespace std;
#define ll long long
#define M 100118947
#define K 364213
#define KK 79921
#define MM 163276871
ll pow(ll x,ll k,ll p){if(!k)return 1;if (k&1) return x*pow(x,k-1,p)%p;ll t=pow(x,k/2,p);return t*t%p;}
char str[1000000];
ll rec[10000000],rec2[10000000];
int main()
{
ll a,b,c,p;int cnt=0;
gets(str);
int len=strlen(str);
for (int i=0;i<len;i++) if (str[i]==' ') rec[i]=70;else rec[i]=str[i]-'A'+30;
for (int i=0;i<len;i=i+4){
for(int j=i;j<min(i+4,len);j++)
{
rec2[cnt]=rec2[cnt]*100+rec[j];
}
cnt++;
}
cout<<cnt<<endl;
for (int i=0;i<cnt;i++)
{
cout<<pow(rec2[i],K,M)%M<<endl;
}
}
解密
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#define B 100098936
#define M 100118947
#define A 364213
#define AA 79921
#define MM 163276871
#define BB 163251312
using namespace std;
#define ll long long
#define F(x,a,b) for (ll x=a;x<=b;x++)
ll x,y,a,b;
void _exgcd(ll a,ll b,ll &x,ll &y){if (!b){x=1;y=0;return;}_exgcd(b,a%b,y,x);y-=x*(a/b);}
void check(){if ((A*x+b*y)-1){if(!(A*(-x)+b*y-1)){x=-x;return;}else{if (!((A*x+b*(-y))-1)){y=-y;return;}else {x=-x;y=-y;}}}}
ll pow(ll x,ll k,ll p){if (!k) return 1;if (k&1) return x*pow(x,k-1,p)%p;else{ll t=pow(x,k/2,p);return t*t%p;}}
int rec[10000000],rec2[10000000];
int main()
{
ll q,p,m;
char strr[1000000];
int len; int cnt1=-1;int cnt2=0;
int nn; cin>>nn;
while (nn--)
{
cin>>strr;
len=strlen(strr);
for (int i=0;i<len;i++)
{
rec[cnt2]=rec[cnt2]*10+strr[i]-'0';
}
cnt2++;
}
F(o,0,cnt2-1)
{
b=-B;
_exgcd(A,b,x,y);
check();
if (x<0) x+=abs(b);
// if (y<0) y+=abs(A);
ll t=pow(rec[o],x,M)%M;
char str[10];
cnt1=-1;
while (t)
{
cnt1++;
if (t%100!=70)
str[cnt1]=t%100+'A'-30;
else str[cnt1]=' ';
t/=100;
}
for (int i=cnt1;i>=0;i--) printf("%c",str[i]);
}
}