【墨鳌】【数论小结 03】【RSA加密算法】

数论小结 03

欧拉函数的应用

RSA加密算法

  1. 选取两个质数 \(p,q\)
  2. \(\varphi(n),n=p\cdot q\),显然:\(\varphi(n)=(p-1)(q-1)\)
  3. 构造公钥 \((n,e)\),选取 \(e\in[2,\varphi(n))\) 并且 \(\gcd(e,\varphi(n))=1\)
  4. 构造私钥 \((n,d)\),求 \(ed\equiv1\mod \varphi(n)\)
  5. 加密过程:\(C\leftarrow M^e\mod n\)
  6. 解密过程:\(M\leftarrow C^d\mod n\)

通讯过程模拟

//
// 有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
// Created by Mo-Ao on 2022-4-29 14:25:00
//

#include "Solution.h"

int main() {
    Solution sol = Solution();

    typedef long long ll;
    /**
     * n=p*q
     * p=10000993
     * q=12072001
     * e=1000000007 (公钥:(n,e))
     * ed≡1 (mod φ(n)) 扩展欧几里得 or 费马小定理 求解 d
     * 注意:这里不可用“费马小定理”求解d,因为此时模数φ(n)不是质数
     * d=115336154889143 (私钥:(n,d))
     * C ← M^e mod n (公钥:(n,e))
     * M ← C^d mod n (私钥:(n,d))
     */
    ll p = 10000993;
    ll q = 12072001;
    ll phi = (p - 1) * (q - 1);
    // 以上参数应当销毁

    ll n = p * q;
    ll e = 1000000007;
    ll d = sol.inv(e, phi);
    //以上两组密钥(n,e),(n,d)由通讯双方持有


    string text = "Hello!";
    auto code = sol.send(text, n, e);

    //通讯中
    cout << "code = ";
    for (auto &ch: code)cout << ch << " ";
    cout << endl;

    auto receivedText = sol.receive(code, n, d);
    cout << receivedText << endl;
    return 0;
}

通讯模板工具

//
// 有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
// Created by Mo-Ao on 2022-4-29 14:25:00
//

#ifndef TESTDEMO_SOLUTION_H
#define TESTDEMO_SOLUTION_H

#include <bits/stdc++.h>

using namespace std;

class Solution {
public:
    typedef long long ll;

    /**
     * 光速乘
     * @param x
     * @param y
     * @param mod
     * @return (x*y) % mod
     */
    ll mul(ll x, ll y, ll mod) {
        ll ret = x * y - (ll) ((long double) x / mod * y + 0.5) * mod;
        return (ret % mod + mod) % mod;
    }

    /**
     * 快速幂
     * @param a
     * @param n
     * @param mod
     * @return pow(a,n) % mod
     */
    ll quick_pow(ll a, ll n, ll mod) {
        if (n == 0) return 1;
        ll x = quick_pow(a, n / 2, mod);
        ll ans = mul(x, x, mod);
        if (n % 2 == 1) ans = mul(ans, a, mod);
        return ans;
    }


    /**
     * 扩展欧几里得算法
     * @param a
     * @param b
     * @param x
     * @param y
     * @return (x,y) for  ax + by = gcd(a,b)
     */
    ll ex_gcd(ll a, ll b, ll &x, ll &y) {
        if (b == 0) {
            x = 1, y = 0;
            return a;
        }
        ll d = ex_gcd(b, a % b, y, x);// 注意:这里已经调换了x,y顺序
        y -= (a / b) * x;
        return d;
    }

    /**
     * 扩展欧几里得求逆元更具一般性
     * @param a
     * @param n
     * @return x for ax ≡ 1 (mod n)
     */
    ll inv(ll a, ll n) {
        ll x, y, d = ex_gcd(a, n, x, y);
        if (d == 1) {
            if (x % n <= 0)
                return x % n + n;
            else
                return x % n;
        }
        return -1;
    }

    /**
     * C ← M^e mod n
     * @param C
     * @param n
     * @param e
     * @return C
     */
    ll encode(ll M, ll n, ll e) {
        return quick_pow(M, e, n);
    }

    /**
     * M ← C^d mod n
     * @param C
     * @param n
     * @param d
     * @return M
     */
    ll decode(ll C, ll n, ll d) {
        return quick_pow(C, d, n);
    }

    /**
     * 发送端 C ← M^e mod n (公钥:(n,e))
     * @param text
     * @param n
     * @param e
     * @return
     */
    vector <ll> send(string&text, ll n, ll e) {
        vector <ll> C;
        for (char&ch: text) {
            ll M = ch;
            C.push_back(encode(M, n, e));
        }
        return C;
    }
    /**
     * 接收端 M ← C^d mod n (私钥:(n,d))
     * @param C
     * @param n
     * @param d
     * @return
     */
    string receive(vector<ll>&C,ll n,ll d){
        string text;
        for(ll&c:C){
            ll C=c;
            text+=(char)(decode(C,n,d));
        }
        return text;
    }

};

#endif //TESTDEMO_SOLUTION_H
posted @ 2022-04-29 14:37  墨鳌  阅读(41)  评论(0编辑  收藏  举报