信息安全导论 实验四 RSA算法(不要求支持大数)

一、实验目的与原理

这次次实验主要难点在于以下三个算法的理解与实现: 1. Rabin-Miller 算法 2. 扩展欧几里得算法 3. 快速幂取余算法 根据前面的算法,我们知道明文和密文都不能大于 n,假设 n 的长度为 L,对于 明文,我们需要按照 L-1 的长度对其分组然后再加密,每组的密文长度 L。解密 的时候使用 L 的长度对其进行分组然后解密,每组的明文长度为 L-1。分组按照 整数从低到高(即从右往左)

二、实验实现

C++中数据的类型与长度参考:

因此,C++最大能支持的十进制是19位的整数。如果要支持更大的整数,需要实现Big Number类。RSA目前比较安全的密钥长度是2048位二进制,即是617位的十进制。因此,C++自带的数据类型无法实现安全的RSA密钥加解密。

为了降低难度,该题不要求实现大数支持,因此只使用C++自带的long long 数据类型。

该实验主要包含三部分:1. 公私钥的生成。在公私钥生成中,有p、q、e三个参数是随机选择的,其中p、q要求是质数,因此需要实现一个函数检查一个整数是否是质数。由p、q的乘积可以得到n:n=p*q,以及n的欧拉函数: φ(n) = (p-1)*(q-1)。e是在(1, φ(n))之间随机选取的整数,需要满足gcd(e, φ(n)) = 1,因此,需要通过扩展欧几里得算法验证取得的e是与φ(n)互质的。d可以通过扩展欧几里得算法求得 。以满足,即

公钥为(n, e),私钥为(n,d)

检查一个整数是否为质数-Rabin-Miller算法,请参考:Miller-Rabin素性测试算法详解_Nicetomeetu-的博客-CSDN博客_millerrabin素数测试算法Miller Rabin算法详解 - 自为风月马前卒 - 博客园BZOJ3667: Rabin-Miller算法 - 自为风月马前卒 - 博客园

扩展欧几里得算法:请参考:【算法学习】扩展欧几里得算法详解及C++代码实现_行仔ovo的博客-CSDN博客_欧几里得算法c++

2. 加密过程,使用加密算法c = m^e mod n,计算出密文c;

3.解密过程,使用私钥d和解密算法m = c^d mod n, ,计算m;

加密和解密过程需要做幂运算取余,如果直接先做幂运算再取余,则很容易出现溢出,因此,我们需要采用快速幂运算取余算法,请参考:https://jlice.top/p/7tbs7/

因此,该次实验主要难点在于以下三个算法的理解与实现:

1. Rabin-Miller算法

2. 扩展欧几里得算法

3. 快速幂取余算法

根据前面的算法,我们知道明文和密文都不能大于n,假设n的长度为L,对于明文,我们需要按照L-1的长度对其分组然后再加密,每组的密文长度L。解密的时候使用L的长度对其进行分组然后解密,每组的明文长度为L-1。分组按照整数从低到高(即从右往左)

输入

第一行是p

第二行是q

第三行是e

第四行是待加密数据

第五行是待解密数据

输出

第一行输出p是否是质数

第二行输出q是否是质数

第三行打印n

第四行打印d

第五行显示输入第四行的加密结果

第六行显示输入第五行的解密结果

输入样例1                                        

67                                                     
43                                                     
13                                                      
281
2154

输出样例1

Yes
Yes
2881
853
325
54

输入样例2 

9973
9397
4889
2020
53185119

输出样例2

Yes
Yes
93716281
42181817
53185119
2020

代码:(有参考)

import java.util.Scanner;
public class test4 {
    private static long x = 0,y = 0;
    public static void main(String[] args) {
        long p,q,e,message1,message2;
        Scanner scanner = new Scanner(System.in);
        p = scanner.nextInt();
        q = scanner.nextInt();
        e = scanner.nextInt();
        message1 = scanner.nextInt();
        message2 = scanner.nextInt();
        if(isPrime(p)){
            System.out.println("Yes");
        }else{
            System.out.println("No");
        }
        System.out.println(isPrime(q) ? "Yes" : "No");
        long n = p*q;
        System.out.println(n);
        long fnd=(p-1)*(q-1);
        //调用欧里几得算法
        if (ouli(e, fnd)==1) {
            long temp;
            if(x<0){
                temp=-1;
            }else{
                temp=1;
            }
            if (temp == -1){
                x = x+fnd;
            }
            System.out.println(x);
        }
        String str1=Long.toString(n);
        int L = str1.length();
        //加密过程
        long truemessage1=fx1(message1, n, e, L, L - 1);
        //解密过程
        long truemessage2=fx2(message2, n, x, L - 1, L);
        System.out.println(truemessage1);
        System.out.println(truemessage2);
    }

    //素数检查
    static boolean isPrime(long n) {
        if(n%2==0){
            return false;
        }
        for(long i= 2;i<n/2+1;i++)
            if(n%i==0) {
                return false;
            }
        return true;
    }

    //扩展欧几里得算法
    private static long ouli(long a, long b) {
        if (b==0) {
            x = 1;
            y = 0;
            return a;
        }
        long r = ouli(b, a%b);
        long temp = y;
        y = x-((a/b)*y);
        x = temp;
        return r;
    }

    //快速幂取余算法
    private static long powMod(long a, long b, long c) {
        long result = 1;
        while (b!=0) {
            if (b%2==1) {
                result = (result*a)%c;
            }
            b = b/2;
            a = (a*a)%c;
        }
        return result;
    }

    //加密算法
    private static long fx1(long m, long n, long e, int L, int length) {
        // m < n
        long x=0;
        if(m<n){
            x=-1;
        }else{
            x=1;
        }
        if (x != 1) {
            return powMod(m, e, n);
        }
        //开始分组
        String a = Long.toString(m);
        //StringBuilder为可变字符串
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = a.length(); i - length > -length; i -= length) {
            String b = a.substring(Math.max(0, i - length), i);
            long temp=Integer.parseInt(b);
            StringBuilder subStr = new StringBuilder(Long.toString(powMod(temp, e, n)));
            while (subStr.length() < L) {
                subStr.insert(0, "0");
            }
            stringBuilder.insert(0, subStr);
        }
        return Integer.parseInt(stringBuilder.toString());
    }

    //解密算法
    private static long fx2(long m, long n, long e, int L, int length) {
        // m < n
        long x = 0;
        if (m < n) {
            x = -1;
        } else {
            x = 1;
        }
        if (x != 1) {
            return powMod(m, e, n);
        }
        //开始分组
        String a = Long.toString(m);
        //StringBuilder为可变字符串
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = a.length(); i - length > -length; i -= length) {
            String b = a.substring(Math.max(0, i - length), i);
            long temp = Integer.parseInt(b);
            StringBuilder subStr = new StringBuilder(Long.toString(powMod(temp, e, n)));
            while (subStr.length() < L) {
                subStr.insert(0, "0");
            }
            stringBuilder.insert(0, subStr);
        }
        return Integer.parseInt(stringBuilder.toString());
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stearm210

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值