Analytic RSA algorithm

Posted by fogofogo on Fri, 11 Feb 2022 21:14:45 +0100

Analytic RSA algorithm

forward: https://www.jianshu.com/p/ff2b538a77e2

  1. RSA algorithm description
    1.1 RSA generates public-private key pairs

Specific examples explain how to generate key pairs

1.Randomly select two unequal prime numbers p and q. 
alice 61 and 53 were selected. (in practical application, the larger the two prime numbers, the harder it is to crack.)

2.calculation p and q Product of n. 
n = 61×53 = 3233
n The length of is the key length. 3233 is written in binary, which is 110010100001. There are 12 bits in total, so the key is 12 bits. In practical application, RSA The key is generally 1024 bits, and 2048 bits for important occasions.

3.calculation n Euler function ofφ(n). call L
 According to the formulaφ(n) = (p-1)(q-1)
alice Calculateφ(3233)Equal to 60×52,3120.

4.Select an integer at random e,That is, the number used for encryption in the public key
 The condition is 1< e < φ(n),And e Andφ(n) Coprime.
alice Between 1 and 3120, 17 were randomly selected. (in practical application, 65537 is often selected.)

5.calculation e aboutφ(n)Modular inverse element of d. That is, the number used to decrypt the key
 so-called"Modular inverse element"It means that there is an integer d,Can make ed coverφ(n)The remainder of the division is 1. ed ≡ 1 (mod φ(n))
alice Found 2753, or 17*2753 mode 3120 = 1

6.take n and e Encapsulated as a public key, n and d Encapsulated as a private key.
stay alice In our example, n=3233,e=17,d=2753,So the public key is (3233,17),The private key is (3233), 2753). 

1.2 RSA encryption

Firstly, the plaintext is grouped by bit string so that the decimal number corresponding to each packet is less than N, and then each packet m is encrypted successively. The sequence composed of ciphertext of all packets is the encryption result of the original message, that is, m meets 0 < = m < n, then the encryption algorithm is:
c≡ m^e mod n; c is ciphertext, and 0 < = C < n.
1.3 RSA decryption

For ciphertext 0 < = C < n, the decryption algorithm is:
m≡ c^d mod n;
1.4 RSA signature verification

RSA cryptosystem can be used for both encryption and digital signature. The following describes the functions of RSA digital signature.
Known public key (e, n), private key d

1.For messages m Signed by: sign ≡ m ^d mod n
2.Verification: for message signature pairs( m,sign),If m ≡ sign ^e mod n,be sign yes m Valid signature of

2.RSA public key cryptosystem

The so-called public key cryptosystem is to use different encryption keys and decryption keys. It is a cryptosystem that "it is computationally infeasible to deduce the decryption key from the known encryption key".

In the public key cryptosystem, the encryption key (i.e. public key) PK is public information, while the decryption key (i.e. secret key) sk needs to be kept confidential. Encryption algorithm E and decryption algorithm D are also public. Although the decryption key SK is determined by the public key PK, SK cannot be calculated according to the PK.

According to the use method of the key, the password can be divided into symmetric password and public key password

Symmetric cipher: a method of using the same key for encryption and decryption

Public key cryptography: encryption and decryption use different passwords, so public key cryptography is usually also known as asymmetric cryptography.
3. Java implements RSA to generate public and private keys and encrypt and decrypt them
3.1 codes are as follows

package com.tencent.blue.utils;

import org.apache.tomcat.util.codec.binary.Base64;
import org.apache.tomcat.util.http.fileupload.IOUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by cuiran on 19/1/9.
 */
public class RSAUtils {

    public static final String CHARSET = "UTF-8";
    public static final String RSA_ALGORITHM = "RSA";


    public static Map<String, String> createKeys(int keySize){
        //Create a KeyPairGenerator object for the RSA algorithm
        KeyPairGenerator kpg;
        try{
            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        }catch(NoSuchAlgorithmException e){
            throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
        }

        //Initialize KeyPairGenerator object, key length
        kpg.initialize(keySize);
        //Generate key pair
        KeyPair keyPair = kpg.generateKeyPair();
        //Get public key
        Key publicKey = keyPair.getPublic();
        String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
        //Get private key
        Key privateKey = keyPair.getPrivate();
        String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
        Map<String, String> keyPairMap = new HashMap<String, String>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);

        return keyPairMap;
    }

    /**
     * Get public key
     * @param publicKey Key string (base64 encoded)
     * @throws Exception
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //Obtain the public Key object through the Key instruction encoded by X509
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
    }

    /**
     * Get private key
     * @param privateKey Key string (base64 encoded)
     * @throws Exception
     */
    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //Obtain the private Key object through the PKCS#8 encoded Key instruction
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    /**
     * Public key encryption
     * @param data
     * @param publicKey
     * @return
     */
    public static String publicEncrypt(String data, RSAPublicKey publicKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
        }catch(Exception e){
            throw new RuntimeException("Encrypted string[" + data + "]Exception encountered while", e);
        }
    }

    /**
     * Private key decryption
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateDecrypt(String data, RSAPrivateKey privateKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
        }catch(Exception e){
            throw new RuntimeException("Decrypt string[" + data + "]Exception encountered while", e);
        }
    }

    /**
     * Private key encryption
     * @param data
     * @param privateKey
     * @return
     */

    public static String privateEncrypt(String data, RSAPrivateKey privateKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
        }catch(Exception e){
            throw new RuntimeException("Encrypted string[" + data + "]Exception encountered while", e);
        }
    }

    /**
     * Public key decryption
     * @param data
     * @param publicKey
     * @return
     */

    public static String publicDecrypt(String data, RSAPublicKey publicKey){
        try{
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
        }catch(Exception e){
            throw new RuntimeException("Decrypt string[" + data + "]Exception encountered while", e);
        }
    }

    private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
        int maxBlock = 0;
        if(opmode == Cipher.DECRYPT_MODE){
            maxBlock = keySize / 8;
        }else{
            maxBlock = keySize / 8 - 11;
        }
        ByteArrayOutputStream
                out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try{
            while(datas.length > offSet){
                if(datas.length-offSet > maxBlock){
                    buff = cipher.doFinal(datas, offSet, maxBlock);
                }else{
                    buff = cipher.doFinal(datas, offSet, datas.length-offSet);
                }
                out.write(buff, 0, buff.length);
                i++;
                offSet = i * maxBlock;
            }
        }catch(Exception e){
            throw new RuntimeException("The encryption and decryption threshold is["+maxBlock+"]An exception occurred while retrieving data for", e);
        }
        byte[] resultDatas = out.toByteArray();
        IOUtils.closeQuietly(out);
        return resultDatas;
    }

    public static void main (String[] args) throws Exception {
        Map<String, String> keyMap = RSAUtils.createKeys(1024);
        String  publicKey = keyMap.get("publicKey");
        String  privateKey = keyMap.get("privateKey");
        System.out.println("Public key: \n\r" + publicKey);
        System.out.println("Private key: \n\r" + privateKey);

        System.out.println("Public key encryption - private key decryption");
        String str = "code_cayden";
        System.out.println("\r Plaintext:\r\n" + str);
        System.out.println("\r Plaintext size:\r\n" + str.getBytes().length);
        String encodedData = RSAUtils.publicEncrypt(str, RSAUtils.getPublicKey(publicKey));
        System.out.println("Ciphertext:\r\n" + encodedData);
        String decodedData = RSAUtils.privateDecrypt(encodedData, RSAUtils.getPrivateKey(privateKey));
        System.out.println("Decrypted text: \r\n" + decodedData);
    }
}

3.2 the operation results are as follows:

Topics: Encryption rsa