首页 > 编程语言 >RSA算法模拟实验报告

RSA算法模拟实验报告

时间:2024-09-26 18:49:45浏览次数:10  
标签:return cout RSA long 算法 num 模拟实验 false base

课程名称

网络安全

实验

成绩

实验

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 素性测试,提高效率(应该跟剪枝差不多)。

报告评分:

标签:return,cout,RSA,long,算法,num,模拟实验,false,base
From: https://blog.csdn.net/taotao6hao/article/details/142526482

相关文章

  • 文心一言 VS 讯飞星火 VS chatgpt (355)-- 算法导论24.2 1题
    一、请在图24-5上运行DAG-SHORTEST-PATHS,使用结点r作为源结点。如果要写代码,请用go语言。文心一言:在Go语言中实现一个DAG(有向无环图)上的最短路径算法(例如,DAG-SHORTEST-PATHS,这通常可以通过简单的拓扑排序加动态规划或者简单的迭代方法来实现,因为DAG中没有环)并不复杂。但......
  • 关于GS匹配算法(Gale_shaply)及想法
    1.GS匹配算法首先第一个问题。简单介绍一下GS匹配算法,Gale-Shapley匹配算法是基于“稳定婚姻”问题提出的。假设有n个男性和m个女性,每个男性都有自己的偏好列表,同样,每个女性也有自己的偏好列表。算法的目标是为这n对男女实现稳定匹配。2.什么是稳定匹配第二个问题就是......
  • [算法] 次小生成树与单源次短路
    发现NOIP大纲里有这个,所以写一写次小生成树分为严格次小生成树和非严格次小生成树,前者要求此生成树的权值和严格大于最小生成树,后者是非严格大于;对于这个问题,我们首先求出原图的最小生成树,然后发现次小生成树是最小生成树只删一条边,然后加一条边得到的,于是我们可以枚举要加的......
  • 算法记录——树
     二叉树3.1二叉树的最大深度思路:二叉树的最大深度=根节点的最大高度。因此本题可以转换为求二叉树的最大高度。        而求高度的时候应该采用后序遍历。遍历顺序为:左右中。每次遍历的节点按后序遍历顺序,先收集左右孩子的最大高度,再最后处理当前节点的最大高......
  • 算法记录——链表
    2.链表2.1判断是否是回文链表1.方法一:利用栈反转链表/***Definitionforsingly-linkedlist.*publicclassListNode{*intval;*ListNodenext;*ListNode(){}*ListNode(intval){this.val=val;}*ListNode(intval,Lis......
  • 中点算法和Bresenham算法画线
    使用EasyXc++库中点算法直线绘制//中点算法划线:横向直线绘制voidDDAline(intx1,inty1,intx2,inty2,intcolor){intx;floatdx,dy,y,k;dx=x2-x1,dy=y2-y1;if(dx==0){for(y=min(y1,y2);y<max(y1,y2);y++){......
  • 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素、977.有序数组的平方。
    704.二分查找总结:防止int溢出:classSolution{public:intsearch(vector<int>&nums,inttarget){intleft=0;intright=nums.size()-1;while(left<=right){intmiddle=(left+right)/2;//intmid=(right-left)/......
  • 算法与数据结构——快速排序
    快速排序快速排序(quicksort)是一种基于分治策略的排序算法,运行高效,应用广泛。快速排序的核心操作是“哨兵划分”,其目标是::选择数组中的某个元素作为“基准数”,将所有小于基准数的元素移到其左侧,而大于基准数的元素移到其右侧。具体流程如下:选取数组最左端元素作为基准数,初始化......
  • JAVA 数据结构与算法 队列的介绍与应用
    一、队列队列是一个有序列表,可以用数组或者链表来实现遵循先入先出的原则。当我们将数据存入队列时称为”addQueue”,addQueue的处理需要有两个步骤:思路分析:将尾指针往后移:rear+1,当front==rear【空】若尾指针rear小于队列的最大下标maxSize-1,则将数据存入rear所......
  • 字符串从入门到退竞(2)——KMP 算法
    约定在文字描述中字符串下标从\(1\)开始,代码中从\(0\)开始。前缀函数对于长\(n\)的字符串\(S\),其前缀函数是一个长\(n\)的数组(数列)\(\pi\),定义如下:若\(S[1..i]\)有相等的真前缀和真后缀(称之为border),\(\pi[i]\)为其长度的最大值;若不存在,\(\pi[i]=0\)。字符串的......