RSA密码初探

RSA密码初探

一。 RSA公私钥生成
1.随机选定两个大素数p, q.
2.计算公钥和私钥的公共模数 n = pq .
3.计算模数n的欧拉函数 φ(n) .
4.选定一个正整数e,使1 < e < φ(n) ,且e与φ(n)互质.(e取最小)
5.计算d,满足 de ≡ 1  (mod φ(n) )(d取最小)
6.n与e决定公钥, n与d决定私钥.
二。加解密
该过程为L给Z发消息,公钥为Z的公钥(n & e), 私钥为Z的私钥(n & d).
1.L欲给Z发一个消息M,他先把M转换为一个大数m < n, 然后用Z的公钥(n & e)把m加密为另一个大数: c = m^e mod n
2.Z收到L发来的大数c,着手解密.通过自己的私钥(n & d),得到原来的大数m: 
 m = c^d mod n
3.再把m转换为M, Z即得到L的原始消息.
这个过程之所以能通过,是因为有如下等式:
 c^d ≡(m^e)^d ≡ m ^(ed) (mod n)
  
若给出p,q,和密文整数序列a[m] ,求解公钥n,e,私钥n,d以及解出明文序列b[m]
1)令x = φ(n) = φ(p) * φ(q) = (p-1)(q-1) (p,q互质且p,q都是质数)
2)e是与x互质的最小正整数,枚举即可
3)de ≡ 1  (mod φ(n) ) ,d最小,枚举,或者逆元(扩欧几里得求逆元,非快速幂,因为φ(n)不一定是质数)4)b[i] = ( a[i] ^ d ) % n (也就是过程2(快速幂取模即可)(有时候可能爆精度快速幂中嵌套快速乘)

例题:
密码破译

描述
近日来勒索病毒的事件频繁发生,小Y对它的加密原理非常感兴趣,研究了一番相关知识之后,他就来给你看他的加密程序,并给你一段密文,和你炫耀说就算把程序给你看你也破解不出来。

你扫了一眼代码发现加密的公式为b =a ^ e%m,其中e是质数。

进一步分析发现m=p∗q,p和q都为质数,p!=q,

作为一个计算机高手,你早就对加密算法烂熟于心,一眼就看出这个程序的算法和原理,找到了破解的方法,发现小Y疏忽在与给了你一个不够大的m。

你知道解密的公式与加密对称,为a=b^d%m。

但是你仍然无法心算解出这个d,因此你需要借助计算机来将密文破解。

输入
第一行有一个整数T表示数据组数。(T<=100)
接着有T组数据,每组数据两行。
第一行有四个数e、p、q和n,其中e、p、q如题所描述,n表示需要解密的数字序列长度。
第二行是需要解密的数字序列a1…an。
1 0<= ai 保证解密的结果即原数列的值小于min(p,q)并大于等于0
1<=n<=100
保证m有且仅有两个不同的质因数p和q,并且一定存在一个题中描述的参数d使得解密公式能够无损解密出所有0~min(p,q)−1范围之间的数字。

输出
对于每组数据输出一行,表示解密后的数字序列,数字之间以空格隔开。

样例输入1
1
5 19 29 3
335 440 514
样例输出1
65 67 77

提示
对于样例,存在d=101使得解密公式成立。
注意m和ai的大小可能超过int的范围

#include
using namespace std;
const int maxn = 100 + 5;
typedef long long ll;

ll exgcd(ll a, ll b,ll &x,ll &y){
    if(!b){
        return x = 1, y = 0, a;
    }
    ll d = exgcd(b , a % b, x, y);
    ll t = x;
    x = y, y = t - (a / b) * y;
    return d;
}

ll get_inv(ll a,ll mod){
    ll x,y;
    exgcd(a,mod,x,y);
    return (x % mod + mod)%mod;
}

ll mul(ll a,ll b,ll mod){
    ll res = 0;
    while(b){
        if(b&1) res = (res + a) % mod;
        a = a * 2 % mod;
        b >>= 1;
    }
    return res;
}

ll fast_pow(ll a,ll b,ll mod){
    ll res = 1;
    while(b){
        if(b&1) res = mul(res,a,mod);
        a = mul(a,a,mod);
        b >>= 1;
    }
    return res;
}

ll a[maxn];

int main(){
    ll p,q,e;
    int T,n;
    scanf("%d",&T);
    while(T--){
        scanf("%lld%lld%lld%d",&e,&p,&q,&n);
        for(int i = 0; i < n; ++i){
            scanf("%lld",&a[i]);
        }
        ll m = p * q;
        ll d = get_inv(e,(p - 1) * (q - 1));
        for(int i = 0; i < n; ++i){
            printf("%lld",fast_pow(a[i],d,m));
            putchar((i == n - 1)?'\n':' ');
        }
    }
    return 0;
}

你可能感兴趣的:(math,RSA)