首先先解决这样一个问题,b和m已知求满足下面条件的x,
这个问题若是没有限制条件的话会变得很棘手,那么假设条件变得更强让gcd(b,m)=1;便会想到利用欧拉函数求出 ϕ(m) ϕ ( m ) ,之后解下面的不定方程。
xk x k - y y ⋅ ⋅ ϕ(m) ϕ ( m ) =1
假设gcd(k,
ϕ(m)
ϕ
(
m
)
)=1,那么一定存在一组非负解x=a,y=b;使得
则有
则可以计算出 x=bamodm x = b a m o d m ,这样便给出了计算模m的k次幂的方法。
于是问题就转化成了如何求 xk x k - y y ⋅ ⋅ ϕ(m) ϕ ( m ) =1,以及 ϕ(m) ϕ ( m ) 前者十分好求利用扩展欧几里得算法可以快速求出
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);}
后者则要用到求
ϕ(m)
ϕ
(
m
)
的公式:
ϕ(m)=(p1k1−p1k1−1)⋅(p2k2−p2k2−1)...(pnkn−pnkn−1)
ϕ
(
m
)
=
(
p
1
k
1
−
p
1
k
1
−
1
)
⋅
(
p
2
k
2
−
p
2
k
2
−
1
)
.
.
.
(
p
n
k
n
−
p
n
k
n
−
1
)
(p为m的因子)
m很小时对于m的因数分解是非常容易的,但是一旦m很大时便非常困难
RSA加密的办法就是利用以上思路,取两个质数p q并求出
ϕ(m)=(p−1)⋅(q−1)
ϕ
(
m
)
=
(
p
−
1
)
⋅
(
q
−
1
)
再取一个k与
ϕ(m)
ϕ
(
m
)
互素,则可以则对 任意x
xk≡b(modm)
x
k
≡
b
(
mod
m
)
都可以求出一个对应的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]);
}
}