[Encryption algorithm] RSA algorithm and code implementation

The RSA algorithm is a widely used public-key cryptography system. Its name comes from the initials of its founders Ron Rivest, Adi Shamir and Leonard Adleman. The RSA algorithm is a cryptographic system based on number theory, which utilizes some theorems and concepts in number theory, such as Fermat's Little Theorem and the difficult problem of decomposing large numbers.

1. Historical introduction

The RSA algorithm was co-invented by Ron Rivest, Adi Shamir and Leonard Adleman in 1977. Public-key cryptosystems had been proposed before, but they were either theoretical or very difficult to implement. The emergence of the RSA algorithm opened the way for the practical application of public key cryptography systems.

2. Code description

RSA is an asymmetric encryption algorithm that uses a pair of keys, one public for encryption and the other secret for decryption. The following is the calculation process of the RSA algorithm:

  • Choose two large prime numbers p and q, and calculate their product n=p*q.
  • Choose a public exponent e, requiring that e and φ(n)=(p-1)*(q-1) (Euler function) are relatively prime, that is, gcd(e, φ(n))=1.
  • Calculate the modulus inverse element d that is relatively prime to e, that is, gcd(d, φ(n))=1 and d*e≡1 mod φ(n).
  • Destroy p and q so that only authorized entities can retrieve them.

Encryption process:

  • For the plaintext message m to be encrypted, convert it into an integer less than n.
  • Encrypt m to get ciphertext c, the calculation formula is c=m^e mod n.
  • Send the ciphertext c to the recipient.

Decryption process:

  • After the receiver receives the ciphertext c, he uses his own private key d to decrypt c and obtains the plaintext m. The calculation formula is m=c^d mod n.
    Since d and φ(n) are mutually prime, according to Fermat’s little theorem, c^d mod n=(m e) d mod n=(m^(ed)) mod n=m^(ed*mod n) mod n=m.
    Insert image description here
package com.example.demo;


import java.io.UnsupportedEncodingException;
import java.math.BigInteger;

import java.util.LinkedList;
import java.util.List;

public class DemoMain {
    
    
    public static void main(String[] args) throws UnsupportedEncodingException {
    
    


        // 选择两个质数p和q
        BigInteger p = new BigInteger("11");
        BigInteger q = new BigInteger("19");

        // 计算n和φ(n)
        BigInteger n = p.multiply(q);

        BigInteger phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));

        System.out.println("n:" + n);
        System.out.println("phi:" + phi);

        // 选择一个公开的指数e,并计算模反元素d
        BigInteger e = new BigInteger("7");

        BigInteger d = e.modInverse(phi);


        // 公钥和私钥
        BigInteger publicKey = e;
        BigInteger privateKey = d;
        System.out.println("公钥:" + publicKey);

        System.out.println("私钥:" + privateKey);

        // 明文消息
        String plaintext = "kexuexiong";

        //一、私钥加密,公钥解密,模拟服务器发消息给客户端
        System.out.println("-------------------------------------私钥加密,公钥解密,模拟服务器发消息给客户端---------------------------------");

        processing(n, e, d, plaintext);


        //二、公钥加密,私钥解密,模拟客户端发消息给服务器
        System.out.println("-------------------------------------公钥加密,私钥解密,模拟客户端发消息给服务器---------------------------------");
         plaintext = "hello ,rose and jeck!!";
        processing(n, d, e, plaintext);

    }

    private static void processing(BigInteger n, BigInteger e, BigInteger d, String plaintext) throws UnsupportedEncodingException {
    
    

        System.out.println("需要加密的明文:"+plaintext);
        // 加密过程
        byte[] bytes = plaintext.getBytes("utf-8");
        List<String> plaintextList = new LinkedList<>();


        for (Byte aByte : bytes) {
    
    
            BigInteger message = new BigInteger(aByte.toString());

            BigInteger ciphertext = message.modPow(d, n);//加密之后的值可能超过Byte的最大值,所以直接用string保存
            plaintextList.add(ciphertext.toString());
        }

        System.out.println("加密后队列:"+plaintextList);


        // 解密过程
        List<Byte> cipherList = new LinkedList<>();

        for (String ciphertext : plaintextList) {
    
    

            BigInteger decryptedMessage = new BigInteger(ciphertext).modPow(e, n);

            cipherList.add(decryptedMessage.byteValue());

        }
        System.out.println("解密后队列信息: " + cipherList);

        byte[]  bytesMsg = new byte[cipherList.size()];

        for (int i = 0; i < cipherList.size(); i++) {
    
    
            bytesMsg[i] = cipherList.get(i);
        }

        System.out.println("解密后信息:" + new String(bytesMsg, "utf-8"));
    }


}

In this example code, we choose two prime numbers p and q, calculate n and φ(n), then choose a public exponent e, and calculate the modular inverse element d. We then encrypt a plaintext message using the public key and decrypt it using the private key. Finally, we print out the encrypted ciphertext and decrypted plaintext.

Output result:

n:209
phi:180
公钥:7
私钥:103
-------------------------------------私钥加密,公钥解密,模拟服务器发消息给客户端---------------------------------
需要加密的明文:kexuexiong
加密后队列:[50, 118, 175, 90, 118, 175, 51, 100, 143, 141]
解密后队列信息: [107, 101, 120, 117, 101, 120, 105, 111, 110, 103]
解密后信息:kexuexiong
-------------------------------------公钥加密,私钥解密,模拟客户端发消息给服务器---------------------------------
需要加密的明文:hello ,rose and jeck!!
加密后队列:[80, 161, 48, 48, 188, 10, 66, 38, 188, 58, 161, 10, 147, 165, 111, 10, 182, 161, 44, 145, 22, 22]
解密后队列信息: [104, 101, 108, 108, 111, 32, 44, 114, 111, 115, 101, 32, 97, 110, 100, 32, 106, 101, 99, 107, 33, 33]
解密后信息:hello ,rose and jeck!!

Process finished with exit code 0

The reason why the RSA algorithm is secure is based on a characteristic fact in number theory: it is easy to combine two large prime numbers into a large number, but it is very difficult to decompose a large number into two prime numbers. In RSA password applications, the public key (n, e) is public, which means that the values ​​of n and n can be known by others. The problem of cracking the RSA password is actually to find d through the values ​​of e and n (np g ) The value of the private key (n, d) can be obtained. If you want to get the value of the private key, you need to get the value of f(n) because ed=1mod f(n). And because f(n)=(p-1) (g-1), the value of f(n) must be found through the known value of n. In other words, the essence of cracking the secret is to find the values ​​of p and g. When p and g are large prime numbers, decomposing the factors p and g from their product p is a recognized mathematical problem and difficult to achieve. Therefore, the security of RSA depends on the number of digits of the public key. The larger the number of digits, the smaller the possibility of decomposing n. Therefore, the n value of this system uses 1024 bits, which increases the difficulty of password cracking. difficulty and improve the security of the system.

Guess you like

Origin blog.csdn.net/qq_22744093/article/details/132733006