信息安全實驗——RSA加密

一、實驗目的

熟悉 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);

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章