RSA算法的简单实现

文章目录

    • 原理和所需用到的技术
    • java实现代码
    • 一道RSA题解

对于RSA算法的原理进行简单讲述和阉割版的实现

原理和所需用到的技术

RSA算法的简单实现_第1张图片

java实现代码


import java.math.BigInteger;
import java.nio.charset.StandardCharsets;

public class RSA {
     
    /**
     * 对以下参数作用和设置进行说明:
     * 对于p,q为已设定的质数
     * fin为根据p,q求出的值
     * n为p,q乘积
     * e为与fin互质的数,用于加密
     * d,k为根据d = (k * fin + 1) / e求出的解密密钥,可以根据扩展欧几里得算法求出
     * 下面还有对于p,q,n,fin,e,k,d生成和求解的随机生成数的方法,但是由于本人对于RSA理解还是
     * 较为浅薄,虽然可以生成符合条件的以上数据,但是任然无法进行逆向解密,所以就使用了一组可以加
     * 解密的固定数据值如上,因此将其设置为final值
     */
    private static final int p = 61;
    private static final int q = 53;
    private static final int fin = 60 * 52; //欧几里得数
    private static final int n = 61 * 53;
    private static final int e = 17;   //加密密钥,公共指数常取3, 17和65537三个值,一般我们直接取e=65537。
    private static final int d = 2753;   //解密密钥
    private static final int k = -15;
    //d = (k * fin + 1) / e
    /**
     * 判断是否是质数
     * @param n 需要判断的数
     * @return
     */
    private static boolean isPrime(int n){
     
        for(int i = 2;i <= Math.sqrt(n);i++){
     
            if(n % i == 0){
     
                return false;
            }
        }
        return true;
    }

    /**
     * 生成一个范围为20-200的伪随机数random
     * @return  random
     */
    private static int random(){
     
        int random = (int ) (Math.random() * 180 + 20 );
        return random;
    }

    /**
     * 计算n的欧拉函数
     * @param n p * q的值
     * @return
     */
    private static int fin(int n){
     
        int fin;
        if(isPrime(n)){
     
            fin = n - 1;
        }else {
     
            fin =  (p - 1) * (q - 1);
        }
//        while (fin % e == 0){
     
//            RSAInit();
//        }
        return fin;
    }

    /**
     * 生成一个e值,这个值的范围为1-fin,且与fin互质
     * @return e
     */
//    private static int randomE(){
     
//        int e = (int )(Math.random() * (fin - 1) + 1);
//        while (fin % e == 0){
     
//            e = (int ) (Math.random() * (fin - 1) + 1);
//        }
//        return e;
//    }

    /**
     * 扩展欧几里得算法
     * @param e
     * @param fin
     * @param xy 任意值,作存数用
     * @return
     */
    private static int gcdEx(int e,int fin,int []xy){
     

        if(fin == 0){
     
            xy[0] = 1;
            xy[1] = 0;
            return e;
        }
        int g = gcdEx(fin,e % fin,xy);
        int temp = xy[0];
        xy[0] = xy[1];
        xy[1] = temp - e / fin * xy[1];
        return g;
    }

    /**
     * 公钥,用于加密
     * @return
     */
    public int pubKey(){
     
        return e;
    }

    /**
     * 私钥 用于解密
     * @return
     */
//    private int priKey(){
     
//        return  d;
//    }

    boolean []isMinus;   //记录文本数据的正负值,由于mod操作获得值只是正数,所以要对原数的正负进行记录和还原
    /**
     * 加密函数进行加密操作
     * 数据加密过程:密文c=m^e mod n
     *
     * @param message -需要进行加密的文本
     * @param pubKey -进行加密的公钥
     * @return encryptMessage -加密后的密文
     */
    public int[] encrypt(byte []message,int pubKey){
     
        isMinus = new boolean[message.length];
        int []encryptMessage = new int[message.length];
        for(int i = 0;i < message.length;i++){
     
            if(message[i] < 0){
     
                isMinus[i] = true;
            }
            BigInteger m = new BigInteger(String.valueOf(message[i]));      //明文
            BigInteger exp = new BigInteger(String.valueOf(e));             //加密密钥
            BigInteger N = new BigInteger(String.valueOf(n));               //模
            BigInteger c = m.modPow(exp,N);                                 //密文
            encryptMessage[i] = c.intValueExact();
        }
        return encryptMessage;
    }

    /**
     * 解密函数用于解密
     * 数据的解密过程:明文m = c^d mod n
     * @param encryptMessage - 需要解密的密文
     * @return decryptMessage -解密后的明文
     */
    public String decrypt(int []encryptMessage) throws ArithmeticException{
     
        byte []decryptMessage = new byte[encryptMessage.length];
        for(int i = 0;i < encryptMessage.length;i++){
     
            if(isMinus[i]){
     
                encryptMessage[i] = encryptMessage[i] * -1;
            }
            BigInteger c = new BigInteger(String.valueOf(encryptMessage[i]));   //需要解密的密文
            BigInteger exp = new BigInteger(String.valueOf(d));              //解密密钥
            BigInteger N = new BigInteger(String.valueOf(n));                   //模
            if(isMinus[i]){
     
                BigInteger m = c.modPow(exp,N).multiply(new BigInteger("-1"));                         //解密出的明文
                decryptMessage[i] = m.byteValueExact();
            }
        }
        return new String(decryptMessage, StandardCharsets.UTF_8);
    }


    public static void RSAInit(){
     
//        p = random();
//        //保证p为质数
//        while (!isPrime(p)){
     
//            p = random();
//        }
//        q = random();
//        // 保证p,q不等,且q为质数
//        while (p == q || !isPrime(q)){
     
//            q = random();
//        }
//        n = p * q;
//        //计算n的欧拉函数
//        fin = fin(n);
//        //选择一个整数e,(与fin互质),作为加密密钥
        e = randomE();
//        //计算模反元素d
//        int []xy = new int[2];
//        gcdEx(e,fin,xy);
//        d = xy[0];
//        k = -1 * xy[1];
    }
}


主函数:

import java.nio.charset.StandardCharsets;
import java.util.Scanner;

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

        RSA rsa = new RSA();        //RSA加解密对象的创建
        rsa.RSAInit();
        //需要加密的信息
        try{
     
//            Scanner in = new Scanner(System.in);
            String message = "这是我的第一个RSA加解密程序";
//            message = in.nextLine();
            int []encryptMessage = rsa.encrypt(message.getBytes(StandardCharsets.UTF_8),rsa.pubKey());//加密文本
            String decryptMessage = rsa.decrypt(encryptMessage);    //解密文本
            for(int x : encryptMessage){
     
                System.out.print(x);
            }
            System.out.println("");
            System.out.println(decryptMessage);
        }catch (Exception e){
     
            e.printStackTrace();
        }

    }
}


运行截图:
在这里插入图片描述

一道RSA题解

  1. 已知RSA算法中,素数p=5,q=7,模数n=35,公钥e=5,明文为bed,对明文进行加解密,使用手工完成RSA公开秘钥密码体制算法加密运算。字母数字映射表如下:

在这里插入图片描述
根据p,q得:

φ(n)=(p-1)(q-1)(当p与q都为质数时)
则:φ(n)=4
6=24
有扩展欧几里得算法求:ed+kφ(n)=1
所以 解密密钥d = 5,k = 1
通过映射表可知bed分别为02 05 04
加密操作:m^e mod n=c(密文)(其中m为需要加密的明文)
解密操作:c^d mod n=m

进行加密操作:
2^5 mod 35=32
5^5 mod 35=10
4^5 mod 35=9
密文:321009

对密文进行解密操作:
32^5 mod 35=2
10^5 mod35=5
9^5 mod 35=4
对照参照表的解密后的明文为bed
RSA算法的简单实现_第2张图片

需要了解更多的可以参考资料:

https://zhuanlan.zhihu.com/p/48249182

https://www.bilibili.com/video/BV14y4y1272w?from=search&seid=1188064992288787574&spm_id_from=333.337.0.0

你可能感兴趣的:(码代码,笔记,算法,java,开发语言)