一、實驗目的
熟悉 RSA 加密的基本思路和流程,完成 RSA 加密算法
二、實驗任務
1.熟悉 RSA 加密的數學基礎知識:素數、歐拉公式、擴展歐幾里得公式等
2.學習使用快速冪算法快速求解大數乘方取模問題
3. 完成 RSA 算法
三、實驗內容
RSA算法實現過程中,應當使用高精度計算算法,否則在輸入多位明文計算時會出現 long long型溢出問題,這裏沒有實現,只做初步學習。
RSA加密算法實現參考代碼:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <algorithm>
using namespace std;
typedef long long ll;
// 最大素數範圍
const int MAX_PRIME_RANGE = 10000;
/*
* 隨機獲取兩個較大質數(2 ~ MAX_PRIME_RANGE)
*/
pair<ll, ll> get_big_prime() {
bool prime[MAX_PRIME_RANGE];
pair<int, int> res;
for (bool &i : prime) {
i = true;
}
prime[0] = false;
prime[1] = false;
for (int i = 2; i <= sqrt(MAX_PRIME_RANGE); i++) {
if (prime[i]) {
for (int j = i; i * j < MAX_PRIME_RANGE; j++) {
prime[i * j] = false;
}
}
}
srand((unsigned) time(NULL));
int index = rand() % MAX_PRIME_RANGE;
int count = 0;
for (int i = index; i >= 0; i--) {
if (prime[i]) {
count++;
if (count == 1) {
res.first = i;
i = rand() % MAX_PRIME_RANGE;
} else if (count == 2) {
res.second = i;
return res;
}
}
}
}
// 快速乘法 a*b
ll fast_time(ll a, ll b) {
ll ans = 0;
while (b) {
if (b & 1) {
ans += a;
}
a += a;
b >>= 1;
}
return ans;
}
/*
* 計算φ(n)
*/
ll __phi_n(ll p, ll q) {
return fast_time(p - 1, q - 1);
}
/*
* 判斷兩數是否互質
*/
bool is_mutual_prime(ll a, ll b) {
ll temp = 0;
while (b != 0) {
temp = b;
b = a % b;
a = temp;
}
return a == 1;
}
/*
* 擴展歐幾里得算法
*/
ll ExGcd(ll a, ll b, ll &x, ll &y) {
if (!b) {
x = 1;
y = 0;
return a;
}
ll ans = ExGcd(b, a % b, x, y);
ll temp = x;
x = y;
y = temp - a / b * y;
return ans;
}
ll getInverse(ll a, ll p) { //a模n的乘法逆元
if (__gcd(a, p) != 1) {
return -1;
}
ll x, y;
ExGcd(a, p, x, y);
return (x + p) % p;
}
pair<ll, ll> prime_pair;
ll n, phi_n, e, d;
/*
* 生成公鑰
*/
void generate_key() {
prime_pair = get_big_prime();
n = fast_time(prime_pair.first, prime_pair.second);
phi_n = __phi_n(prime_pair.first, prime_pair.second);
e = 0;
for (int i = 2; i < phi_n; i++) {
if (is_mutual_prime(i, phi_n)) {
e = i;
break;
}
}
if (e != 0) {
d = getInverse(e, phi_n);
}
printf("public key: (%lli, %lli)\n", n, e);
printf("private key: (%lli, %lli)\n", n, d);
}
//快速冪取餘a^b%c
ll mod_exp(ll a, ll b, ll c) {
ll res = 1;
a = a % c;
while (b) {
//b的二進制和1的二進制進行位的按位與運算,其實等價於if(b%2==1)起到判斷奇偶的功能,但計算機的位運算比較快。
if (b & 1) {
res = res * a % c;
}
a = a * a % c;
// b的二進制數右移一位賦值給b,右移時高位空缺補零。類比十進制數100右移相當於100/10=10;
// b>>1 等價於b/2;但計算機的位運算比較快。
b >>= 1;
}
return res;
}
ll encrypt(int m) {
return mod_exp(m, e, n);
}
ll decrypt(ll c) {
return mod_exp(c, d, n);
}
int main() {
generate_key();
int m;
cout << "輸入要加密的數字,不超過8位:" << endl;
cin >> m;
ll c = encrypt(m);
cout << "加密後: " << c << endl;
cout << "解密後: " << decrypt(c);
}