【墨鳌】【数论小结 03】【RSA加密算法】
数论小结 03
欧拉函数的应用
RSA加密算法
- 选取两个质数 \(p,q\)
- 求 \(\varphi(n),n=p\cdot q\),显然:\(\varphi(n)=(p-1)(q-1)\)
- 构造公钥 \((n,e)\),选取 \(e\in[2,\varphi(n))\) 并且 \(\gcd(e,\varphi(n))=1\)
- 构造私钥 \((n,d)\),求 \(ed\equiv1\mod \varphi(n)\)
- 加密过程:\(C\leftarrow M^e\mod n\)
- 解密过程:\(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
~~Jason_liu O(∩_∩)O