RSA encryption and decryption (JAVA)

Keywords: Java OpenSSL

RSA encryption and decryption (JAVA)

Record how java uses RSA. There are three main methods. They are basically the same, but the ways to obtain public key and private key are different. In summary, they are:
1. KeyPairGenerator obtains key
2. String get key
3. Module and exponent get key

Method 1:

Use KeyPairGenerator to generate public key and key directly. Generally, private key is reserved to server and public key to client

package com.michael.RSA;

import javax.crypto.Cipher;
import java.security.*;
import java.util.Base64;

public class RSACryptography {

    public static String data = "hello world";

    public static void main(String[] args) {
        KeyPair keyPair = genKeyPair(1024);

        // Get the public key and print it out in base64 format
        PublicKey publicKey = keyPair.getPublic();
        System.out.println("Public key:" + base64Encode(publicKey.getEncoded()));

        // Get the private key and print it out in base64 format
        PrivateKey privateKey = keyPair.getPrivate();
        System.out.println("Private key:" + base64Encode(privateKey.getEncoded()));

        // Public key encryption
        byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
        System.out.println("After encryption:" + new String(encryptedBytes));

        // Private key decryption
        byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
        System.out.println("After decryption:" + new String(decryptedBytes));
    }

    public static String base64Encode(byte[] src) {
        return new String(Base64.getEncoder().encode(src));
    }

    /**
     * Generate key pair
     *
     * @param keyLength
     * @return
     */
    public static KeyPair genKeyPair(int keyLength) {
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(1024);
            return keyPairGenerator.generateKeyPair();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Public key encryption
     *
     * @param content
     * @param publicKey
     * @return
     */
    public static byte[] encrypt(byte[] content, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");// java default "RSA"="RSA/ECB/PKCS1Padding"
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Private key decryption
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static byte[] decrypt(byte[] content, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

Method 2:

Method 1 is only used to generate the key. The generated key needs to be saved in the local file, so in general, the client will not call KeyPairGenerator to generate the key.
You can save the key obtained by the method to a file, and we can read it directly next time.
If it is saved in a file in the form of String, then you can directly use the read String to generate the key.
You can also use openssl to generate

package com.michael.RSA;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.*;
import java.util.Base64;

public class RSACryptography2 {

    public static String data = "hello world";

    public static String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCISLP98M/56HexX/9FDM8iuIEQozy6kn2JMcbZS5/BhJ+U4PZIChJfggYlWnd8NWn4BYr2kxxyO8Qgvc8rpRZCkN0OSLqLgZGmNvoSlDw80UXq90ZsVHDTOHuSFHw8Bv//B4evUNJBB8g9tpVxr6P5EJ6FMoR/kY2dVFQCQM4+5QIDAQAB";
    public static String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIhIs/3wz/nod7Ff/0UMzyK4gRCjPLqSfYkxxtlLn8GEn5Tg9kgKEl+CBiVad3w1afgFivaTHHI7xCC9zyulFkKQ3Q5IuouBkaY2+hKUPDzRRer3RmxUcNM4e5IUfDwG//8Hh69Q0kEHyD22lXGvo/kQnoUyhH+RjZ1UVAJAzj7lAgMBAAECgYAVh26vsggY0Yl/Asw/qztZn837w93HF3cvYiaokxLErl/LVBJz5OtsHQ09f2IaxBFedfmy5CB9R0W/aly851JxrI8WAkx2W2FNllzhha01fmlNlOSumoiRF++JcbsAjDcrcIiR8eSVNuB6ymBCrx/FqhdX3+t/VUbSAFXYT9tsgQJBALsHurnovZS1qjCTl6pkNS0V5qio88SzYP7lzgq0eYGlvfupdlLX8/MrSdi4DherMTcutUcaTzgQU20uAI0EMyECQQC6il1Kdkw8Peeb0JZMHbs+cMCsbGATiAt4pfo1b/i9/BO0QnRgDqYcjt3J9Ux22dPYbDpDtMjMRNrAKFb4BJdFAkBMrdWTZOVc88IL2mcC98SJcII5wdL3YSeyOZto7icmzUH/zLFzM5CTsLq8/HDiqVArNJ4jwZia/q6Fg6e8KO2hAkB0EK1VLF/ox7e5GkK533Hmuu8XGWN6I5bHnbYd06qYQyTbbtHMBrFSaY4UH91Qwd3u9gAWqoCZoGnfT/o03V5lAkBqq8jZd2lHifey+9cf1hsHD5WQbjJKPPIb57CK08hn7vUlX5ePJ02Q8AhdZKETaW+EsqJWpNgsu5wPqsy2UynO";

    public static void main(String[] args) {

        //Get public key
        PublicKey publicKey = getPublicKey(PUBLIC_KEY);

        //Get private key
        PrivateKey privateKey = getPrivateKey(PRIVATE_KEY);

        //Public key encryption
        byte[] encryptedBytes = encrypt(data.getBytes(), publicKey);
        System.out.println("After encryption:" + new String(encryptedBytes));

        //Private key decryption
        byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
        System.out.println("After decryption:" + new String(decryptedBytes));
    }

    /**
     * Convert the base64 encoded public key string to a PublicKey instance
     *
     * @param publicKey
     * @return
     */
    public static PublicKey getPublicKey(String publicKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes());
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(keySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Convert the base64 encoded private key string to a PrivateKey instance
     *
     * @param privateKey
     * @return
     */
    public static PrivateKey getPrivateKey(String privateKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(privateKey.getBytes());
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(keySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Public key encryption
     *
     * @param content
     * @param publicKey
     * @return
     */
    public static byte[] encrypt(byte[] content, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");// java default "RSA"="RSA/ECB/PKCS1Padding"
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Private key decryption
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static byte[] decrypt(byte[] content, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

Method 3:

In addition to saving the key string, other methods generally save only modulus, e and d (exponent) of the public key and private key; where, n, e and d can be obtained in this way, and can be saved in the local file after obtaining.

//Get public key
RSAPublicKey publicKey=(RSAPublicKey) getPublicKey(publicKeyString);
BigInteger modulus1=publicKey.getModulus();
BigInteger exponent1=publicKey.getPublicExponent();

//Get private key
RSAPrivateKey privateKey=(RSAPrivateKey) getPrivateKey(privateKeyString);       
BigInteger modulus2=privateKey.getModulus();
BigInteger exponent2=privateKey..getPrivateExponent();

Suppose we have read the module and exponent from the file:

package com.michael.RSA;

import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;

public class RSACryptography3 {

    public static String data = "hello world";

    public static String MODULUS = "95701876885335270857822974167577168764621211406341574477817778908798408856077334510496515211568839843884498881589280440763139683446418982307428928523091367233376499779842840789220784202847513854967218444344438545354682865713417516385450114501727182277555013890267914809715178404671863643421619292274848317157";

    public static String PUBLIC_EXPONENT = "65537";

    public static String PRIVATE_EXPONENT = "15118200884902819158506511612629910252530988627643229329521452996670429328272100404155979400725883072214721713247384231857130859555987849975263007110480563992945828011871526769689381461965107692102011772019212674436519765580328720044447875477151172925640047963361834004267745612848169871802590337012858580097";

    public static void main(String[] args) throws Exception {
        //Get public key from n and e
        PublicKey publicKey = getPublicKey(MODULUS, PUBLIC_EXPONENT);

        //Get private key from n and d
        PrivateKey privateKey = getPrivateKey(MODULUS, PRIVATE_EXPONENT);

        //Public key encryption
        String encrypted = encrypt(data, publicKey);
        System.out.println("After encryption:" + encrypted);

        //Private key decryption
        String decrypted = decrypt(encrypted, privateKey);
        System.out.println("After decryption:" + new String(decrypted));
    }

    /**
     * Convert the base64 encoded public key string to a PublicKey instance
     *
     * @param modulusStr
     * @param exponentStr
     * @return
     */
    public static PublicKey getPublicKey(String modulusStr, String exponentStr) {
        try {
            BigInteger modulus = new BigInteger(modulusStr);
            BigInteger exponent = new BigInteger(exponentStr);
            RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(modulus, exponent);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(publicKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Convert the base64 encoded private key string to a PrivateKey instance
     *
     * @param modulusStr
     * @param exponentStr
     * @return
     */
    public static PrivateKey getPrivateKey(String modulusStr, String exponentStr) {
        try {
            BigInteger modulus = new BigInteger(modulusStr);
            BigInteger exponent = new BigInteger(exponentStr);
            RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(privateKeySpec);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * The public key is encrypted and converted to hexadecimal string for printing
     *
     * @param content
     * @param publicKey
     * @return
     */
    public static String encrypt(String content, PublicKey publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");// java default "RSA"="RSA/ECB/PKCS1Padding"
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            int splitLength = ((RSAPublicKey) publicKey).getModulus().bitLength() / 8 - 11;
            byte[][] arrays = splitBytes(content.getBytes(), splitLength);
            StringBuffer sb = new StringBuffer();
            for (byte[] array : arrays) {
                sb.append(bytesToHexString(cipher.doFinal(array)));
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * The private key is decrypted and converted to hexadecimal string for printing
     *
     * @param content
     * @param privateKey
     * @return
     */
    public static String decrypt(String content, PrivateKey privateKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            int splitLength = ((RSAPrivateKey) privateKey).getModulus().bitLength() / 8;
            byte[] contentBytes = hexString2Bytes(content);
            byte[][] arrays = splitBytes(contentBytes, splitLength);
            StringBuffer sb = new StringBuffer();
            for (byte[] array : arrays) {
                sb.append(new String(cipher.doFinal(array)));
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Split byte array
     *
     * @param bytes
     * @param splitLength
     * @return
     */
    public static byte[][] splitBytes(byte[] bytes, int splitLength) {
        int x; //Quotient, number of data split groups, when the remainder is not 0 + 1
        int y; //Remainder
        y = bytes.length % splitLength;
        if (y != 0) {
            x = bytes.length / splitLength + 1;
        } else {
            x = bytes.length / splitLength;
        }
        byte[][] arrays = new byte[x][];
        byte[] array;
        for (int i = 0; i < x; i++) {
            if (i == x - 1 && bytes.length % splitLength != 0) {
                array = new byte[bytes.length % splitLength];
                System.arraycopy(bytes, i * splitLength, array, 0, bytes.length % splitLength);
            } else {
                array = new byte[splitLength];
                System.arraycopy(bytes, i * splitLength, array, 0, splitLength);
            }
            arrays[i] = array;
        }
        return arrays;
    }

    /**
     * byte Array to hexadecimal string
     *
     * @param bytes
     * @return
     */
    public static String bytesToHexString(byte[] bytes) {
        StringBuffer sb = new StringBuffer(bytes.length);
        String sTemp;
        for (int i = 0; i < bytes.length; i++) {
            sTemp = Integer.toHexString(0xFF & bytes[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * Hexadecimal string to byte array
     *
     * @param hex
     * @return
     */
    public static byte[] hexString2Bytes(String hex) {
        int len = (hex.length() / 2);
        hex = hex.toUpperCase();
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }

    private static byte toByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
}

Posted by gufmn on Thu, 30 Apr 2020 05:08:53 -0700