RSA算法模拟实验报告

课程名称

网络安全

实验

成绩

实验

RSA算法模拟

学号

姓名

日期

2024.9.24

一、实验目的

(1)学习RSA基本算法

(2)学习指数求模运算

(3)学习逆元的求法

二、实验原理

  1. 生成两个大素数 p 和 q;
  2. 计算这两个素数的乘积 n= p * q;
  3. 计算小于n并且与n互质的整数的个数,即欧拉函数     φ(n) = (p - 1) * (q - 1);
  4. 随机选择一个加密密钥e,使e满足1< e < φ(n),并且e和φ(n)互质;
  5. 利用欧几里德扩展算法计算e的逆元d,以满足:         e * d ≡ 1 mod φ(n)
  6. 公钥PK={e, n};对应的私钥SK={d}
  7. 加密运算:C=Me mod n(如何防止溢出)
  8. 解密运算M=Cd mod n (如何防止溢出)

三、实验环境

操作系统:windows

运行环境:VC6.0或DEV C++

四、实验步骤

(1)具体实现

#include <iostream>

#include <vector>

#include <ctime>

#include <cstdlib>

using namespace std;

// 模幂运算,防止溢出

long long modularExponentiation(long long base, long long exponent, long long modulus) {

    long long result = 1;

    base %= modulus;

    while (exponent > 0) {

        if (exponent % 2 == 1)

            result = (result * base) % modulus;

        exponent >>= 1;

        base = (base * base) % modulus;

    }

    return result;

}

// 判断素数

bool isPrime(long long num) {

    if (num < 2) return false;

    if (num == 2 || num == 3) return true;

    if (num % 2 == 0 || num % 3 == 0) return false;

    long long i = 5;

    while (i * i <= num) {

        if (num % i == 0 || num % (i + 2) == 0) return false;

        i += 6;

    }

    return true;

}

// Miller-Rabin 素性测试

bool isPrimeMillerRabin(long long n, int iterations = 5) {

    if (n < 2) return false;

    if (n == 2 || n == 3) return true;

    if (n % 2 == 0) return false;

    long long d = n - 1;

    int s = 0;

    while (d % 2 == 0) {

        d /= 2;

        s++;

    }

    for (int i = 0; i < iterations; i++) {

        long long a = rand() % (n - 3) + 2;

        long long x = modularExponentiation(a, d, n);

        if (x == 1 || x == n - 1) continue;

        bool found = false;

        for (int r = 1; r < s; r++) {

            x = (x * x) % n;

            if (x == n - 1) {

                found = true;

                break;

            }

        }

        if (!found) return false;

    }

    return true;

}

// 生成大素数

long long generatePrime() {

    long long prime;

    while (true) {// 增加生成的随机数范围,以获得更大的素数

    prime = rand() % 10000 + 10000;

    if (isPrime(prime)) {

        break;

    }

}

    return prime;

}

// 计算两个数的最大公约数

long long gcd(long long a, long long b) {

    while (b!= 0) {

        long long temp = b;

        b = a % b;

        a = temp;

    }

    return a;

}

// 扩展欧几里得算法

long long extendedEuclidean(long long a, long long b, long long& x, long long& y) {

    if (b == 0) {

        x = 1;

        y = 0;

        return a;

    }

    long long x1, y1;

    long long gcd = extendedEuclidean(b, a % b, x1, y1);

    x = y1;

    y = x1 - (a / b) * y1;

    return gcd;

}

// 计算模逆元

long long modInverse(long long a, long long m) {

    long long x, y;

    long long g = extendedEuclidean(a, m, x, y);

    if (g!= 1) return -1;

    return (x % m + m) % m;

}

int main() {

    long long p, q, n, ol, e, d;

    p = generatePrime();

    q = generatePrime();

    n = p * q;

    ol = (p - 1) * (q - 1);

    while (gcd(e, ol)!= 1){

     e = rand() % ol;

    }

    d = modInverse(e, ol);

    long long message = 123;

    long long ciphertext = modularExponentiation(message, e, n);

    long long decryptedMessage = modularExponentiation(ciphertext, d, n);

    cout << "p:" << p << endl;

    cout << "q:" << q << endl;

    cout << "n:" << n << endl;

    cout << "欧拉:" << ol << endl;

    cout << "加密密匙:" << e << endl;

    cout << "逆元:" << d << endl;

    cout << "原始消息:" << message << endl;

    cout << "加密后的消息:" << ciphertext << endl;

    cout << "解密后的消息(字符形式):" << decryptedMessage << endl;

    return 0;

}

五、实验结论

【密码学基础】RSA加密算法(图片来自于这一篇文章)

1、了解了一点防溢出(大整数类型和合适的分解计算)

之前也遇到过类似的(好像是二分查找),就是 (l+r)/2  (r+l)>>1,需要写成 (r-l)/2+l  ((r-l)>>1)+l,从数学的角度上来看,这两种写法是一样的,但是第一种是有可能造成溢出的(l+r)

比如说这里的加密:就可以分解成这样:

85×85 = 7225,7225mod143 = 74
74×85 = 6290,6290mod143 = 49
49×85 = 4165,4165mod143 = 104
104×85 = 8840,8840mod143 = 109
109×85 = 9265,9265mod143 = 123

  1. 又回忆起了被c++支配的恐惧(写不习惯)

比如函数要在main函数之前才能调用,但是java习惯性的直接调。

  1. Miller-Rabin 素性测试

在判断大素数时,可以用Miller-Rabin 素性测试,提高效率(应该跟剪枝差不多)。

报告评分:

RSA算法是一种非对称加密算法,使用公钥进行加密,私钥进行解密。本实验将使用C语言实现RSA算法。 1. 生成公钥和私钥 首先,我们需要生成RSA算法所需的公钥和私钥。生成过程如下: 1.1 选择两个大质数p和q,计算它们的乘积n=p*q。 1.2 计算欧拉函数φ(n)=(p-1)*(q-1)。 1.3 选择一个整数e,满足1<e<φ(n)且e与φ(n)互质。 1.4 计算e关于φ(n)的模反元素d,即满足e*d mod φ(n)=1的整数d。 1.5 公钥为(n,e),私钥为(n,d)。 C语言代码如下: ``` #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> int is_prime(int n) { if (n < 2) { return 0; } for (int i = 2; i <= sqrt(n); i++) { if (n % i == 0) { return 0; } } return 1; } int gcd(int a, int b) { if (b == 0) { return a; } return gcd(b, a % b); } int mod_inverse(int a, int m) { int m0 = m, t, q; int x0 = 0, x1 = 1; if (m == 1) { return 0; } while (a > 1) { q = a / m; t = m; m = a % m, a = t; t = x0; x0 = x1 - q * x0; x1 = t; } if (x1 < 0) { x1 += m0; } return x1; } void generate_key(int *n, int *e, int *d) { srand((unsigned int)time(NULL)); int p, q, phi_n; do { p = rand() % 100 + 1; } while (!is_prime(p)); do { q = rand() % 100 + 1; } while (!is_prime(q)); *n = p * q; phi_n = (p - 1) * (q - 1); do { *e = rand() % phi_n + 1; } while (gcd(*e, phi_n) != 1); *d = mod_inverse(*e, phi_n); } int main() { int n, e, d; generate_key(&n, &e, &d); printf("public key: (%d, %d)\n", n, e); printf("private key: (%d, %d)\n", n, d); return 0; } ``` 2. 加密和解密 生成公钥和私钥后,我们可以使用公钥进行加密,使用私钥进行解密。加密和解密的过程如下: 2.1 加密:将明文m进行加密,得到密文c=m^e mod n。 2.2 解密:将密文c进行解密,得到明文m=c^d mod n。 C语言代码如下: ``` #include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> int is_prime(int n) { if (n < 2) { return 0; } for (int i = 2; i <= sqrt(n); i++) { if (n % i == 0) { return 0; } } return 1; } int gcd(int a, int b) { if (b == 0) { return a; } return gcd(b, a % b); } int mod_inverse(int a, int m) { int m0 = m, t, q; int x0 = 0, x1 = 1; if (m == 1) { return 0; } while (a > 1) { q = a / m; t = m; m = a % m, a = t; t = x0; x0 = x1 - q * x0; x1 = t; } if (x1 < 0) { x1 += m0; } return x1; } void generate_key(int *n, int *e, int *d) { srand((unsigned int)time(NULL)); int p, q, phi_n; do { p = rand() % 100 + 1; } while (!is_prime(p)); do { q = rand() % 100 + 1; } while (!is_prime(q)); *n = p * q; phi_n = (p - 1) * (q - 1); do { *e = rand() % phi_n + 1; } while (gcd(*e, phi_n) != 1); *d = mod_inverse(*e, phi_n); } int mod_pow(int a, int b, int m) { int result = 1; while (b > 0) { if (b & 1) { result = (result * a) % m; } a = (a * a) % m; b >>= 1; } return result; } int encrypt(int m, int e, int n) { return mod_pow(m, e, n); } int decrypt(int c, int d, int n) { return mod_pow(c, d, n); } int main() { int n, e, d; generate_key(&n, &e, &d); printf("public key: (%d, %d)\n", n, e); printf("private key: (%d, %d)\n", n, d); int m = 1234; int c = encrypt(m, e, n); printf("encrypted message: %d\n", c); int decrypted_m = decrypt(c, d, n); printf("decrypted message: %d\n", decrypted_m); return 0; } ``` 以上就是使用C语言实现RSA算法的过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值