RSA解密-第十届Java研究生组E题

  • 1、题目描述
  • 2、解题思路
  • 3、完整代码

1、题目描述

  本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

  RSA 是一种经典的加密算法。它的基本加密过程如下。

  首先生成两个质数 p,q,令 n=pq,设 d 与 (p−1)⋅(q−1) 互质,则可找到 e 使得 RSA解密-第十届Java研究生组E题_Math 除(p−1)⋅(q−1) 的余数为11。

  n,d,e 组成了私钥,n,d 组成了公钥。

  当使用公钥加密一个整数 X 时(小于 n),计算RSA解密-第十届Java研究生组E题_Math_02,则C是加密后的密文。

  当收到密文C 时,可使用私钥解开,计算公式为RSA解密-第十届Java研究生组E题_算法_03

  例如,当 p=5,q=11,d=3 时,n=55,e=27。

RSA解密-第十届Java研究生组E题_数论_04。 解密数字 19,得 RSA解密-第十届Java研究生组E题_数论_05

  现在你知道公钥中 n*=1001733993063167141,d=212353,同时你截获了别人发送的密文 C=20190324,请问,原文是多少?

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

2、解题思路

牵扯到数论的东西想证明都很难,我们掌握结论即可。

RSA解密-第十届Java研究生组E题_数论_06,则e是d模RSA解密-第十届Java研究生组E题_蓝桥杯_07的乘法逆元(前提是d与RSA解密-第十届Java研究生组E题_Math_08),Java中的BigInteger类型提供了求乘法逆元的API,我们直接调用就行。

RSA解密-第十届Java研究生组E题_算法_09

RSA解密-第十届Java研究生组E题_算法_03求解出原文,但是想求出e就得先求出p和q。

RSA解密-第十届Java研究生组E题_java_11互质(互质的意思是最大公约数是1),这里我用暴力遍历出p和q,由于是填空题,n的数字很大,这个遍历求p和q花费了几秒钟的时间。

//p=891234941   q=1123984201
//找p和q   其中d与(p-1)(q-1)互质:也就是最大公约数是1
public static List<Long> findPQ(long n,long d){
    ArrayList<Long> list = new ArrayList<>();
    for (long i = 2L; i <=Math.sqrt(n); i++) {
        if(n%i==0&&gcd(d,(n/i-1)*(i-1))==1&&isPrime(i)&&isPrime(n/i)){
            list.add(i);
            list.add(n/i);
        }
    }
    return list;
}

  然后根据p和q的值求e,这个直接调用惩罚逆元的API即可

//由于d.e%(p-1)(q-1)==1,利用逆元求解e的值
BigInteger e = d.modInverse(p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)));

RSA解密-第十届Java研究生组E题_算法_03计算出最终结果即可。

BigInteger res = c.modPow(e, n);

RSA解密-第十届Java研究生组E题_蓝桥杯_13

3、完整代码

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {

//        System.out.println(findPQ(1001733993063167141L,212353L));
        BigInteger n = new BigInteger("1001733993063167141");
        BigInteger d = new BigInteger("212353");
        BigInteger c = new BigInteger("20190324");

        BigInteger p = new BigInteger("891234941");
        BigInteger q = new BigInteger("1123984201");
        //由于d.e%(p-1)(q-1)==1,利用逆元求解e的值
        BigInteger e = d.modInverse(p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE)));

        //原文:X=C^e %n
        BigInteger res = c.modPow(e, n);
        System.out.println(res);
    }
    //p=891234941   q=1123984201
    //找p和q   其中d与(p-1)(q-1)互质:也就是最大公约数是1
    public static List<Long> findPQ(long n,long d){
        ArrayList<Long> list = new ArrayList<>();
        for (long i = 2L; i <=Math.sqrt(n); i++) {
            if(n%i==0&&gcd(d,(n/i-1)*(i-1))==1&&isPrime(i)&&isPrime(n/i)){
                list.add(i);
                list.add(n/i);
            }
        }
        return list;
    }
    public static boolean isPrime(long n){
        if(n==0||n==1){
            return false;
        }
        for (int i = 2; i <=Math.sqrt(n) ; i++) {
            if(n%i==0){
                return false;
            }
        }
        return true;
    }
    //求gcd
    public static long gcd(long a,long b){
        if(b==0){
            return a;
        }
        long min = Math.min(a, b);
        long max = Math.max(a, b);
        return gcd(min,max%min);
    }
}

RSA解密-第十届Java研究生组E题_算法_14