RSA encryption in Java and JavaScript

Using RSA encryption to:

  1. Encrypt plain text in Java and decrypt cypher text in JavaScript.
  2. Encrypt plain text in JavaScript and decrypt cypher text in Java.

Encryption in JavaScript side

import JSEncrypt from "../lib/jsencrypt.min";

class TravisRsa {
    constructor() {
    }

    encrypt(plainText) {
        let encrypt = new JSEncrypt();
        encrypt.setPublicKey(this._publicKey);
        let cipherText = encrypt.encrypt(plainText);
        return cipherText;
    }

    decrypt(cipherText) {
        let decrypt = new JSEncrypt();
        decrypt.setPrivateKey(this._privateKey);
        let plainText = decrypt.decrypt(cipherText);
        return plainText;
    }

    get publicKey() {
        return this._publicKey;
    }

    set publicKey(value) {
        this._publicKey = value;
    }

    get privateKey() {
        return this._privateKey;
    }

    set privateKey(value) {
        this._privateKey = value;
    }

}

export default TravisRsa;

Usage:

this._rsa = new TravisRsa();
this._rsa.publicKey = ''; // Public key in PEM format
let encrypted = this._rsa.encrypt('This is plain text.');
this._rsa.privateKey = ''; // Private key in PEM format
let decrypted = this._rsa.decrypt(encrypted);
console.log('encrypted: ' + encrypted);
console.log('decrypted: ' + decrypted);

Encryption in Java side

package me.travistran.util.encyption;

import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import javax.xml.bind.DatatypeConverter;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class TravisRsa implements Serializable {

    public enum ModeEnum {
        PKCS1,
        OAEP
    }

    public enum DataTypeEnum {
        HEX,
        BASE64
    }

    private static final Logger LOGGER = Logger.getLogger(TravisRsa.class);

    private DataTypeEnum dataType = DataTypeEnum.BASE64;
    private ModeEnum mode = ModeEnum.PKCS1;
    private PrivateKey privateKey;
    private PublicKey publicKey;

    public TravisRsa() {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(2048);
            KeyPair pair = keyGen.generateKeyPair();
            privateKey = pair.getPrivate();
            publicKey = pair.getPublic();
        } catch (Exception e) {
            LOGGER.error(e);
        }
    }

    public TravisRsa(int keySize) {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(keySize);
            KeyPair pair = keyGen.generateKeyPair();
            privateKey = pair.getPrivate();
            publicKey = pair.getPublic();
        } catch (Exception e) {
            LOGGER.error(e);
        }
    }

    public static String getBase64PublicKey(PublicKey publicKey) {
        return toBase64(publicKey.getEncoded());
    }

    public static String getBase64PrivateKey(PrivateKey privateKey) {
        return toBase64(privateKey.getEncoded());
    }

    public static PublicKey getPublicKey(String base64PublicKey) {
        try {
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(fromBase64(base64PublicKey));
            return KeyFactory.getInstance("RSA").generatePublic(keySpec);
        } catch (Exception e) {
            LOGGER.error(e);
        }
        return null;
    }

    public static PrivateKey getPrivateKey(String base64PrivateKey) {
        try {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(fromBase64(base64PrivateKey));
            return KeyFactory.getInstance("RSA").generatePrivate(keySpec);
        } catch (Exception e) {
            LOGGER.error(e);
        }
        return null;
    }

    public byte[] encrypt(String plainText, PublicKey publicKey) throws Exception {
        Cipher cipher = getCipher();
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
    }

    public byte[] decrypt(byte[] cipherText, PrivateKey privateKey) throws Exception {
        Cipher cipher = getCipher();
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(cipherText);
    }

    public String encrypt(String plainText, String base64PublicKey) throws Exception {
        byte[] cipherText = encrypt(plainText, getPublicKey(base64PublicKey));
        if (DataTypeEnum.BASE64.equals(dataType)) {
            return toBase64(cipherText);
        } else {
            return toHex(cipherText);
        }
    }

    public String decrypt(String cipherText, String base64PrivateKey) throws Exception {
        byte[] cipherBytes;
        if (DataTypeEnum.BASE64.equals(dataType)) {
            cipherBytes = fromBase64(cipherText);
        } else {
            cipherBytes = fromHex(cipherText);
        }
        return new String(decrypt(cipherBytes, getPrivateKey(base64PrivateKey)), StandardCharsets.UTF_8);
    }

    public String encrypt(String plainText) throws Exception {
        return encrypt(plainText, getBase64PublicKey(publicKey));
    }

    public String decrypt(String cipherText) throws Exception {
        return decrypt(cipherText, getBase64PrivateKey(privateKey));
    }

    private Cipher getCipher() throws Exception {
        if (ModeEnum.OAEP.equals(mode)) {
            return Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding", new BouncyCastleProvider());
        } else {
            return Cipher.getInstance("RSA/ECB/PKCS1Padding");
        }
    }

    private static byte[] fromBase64(String str) {
        return DatatypeConverter.parseBase64Binary(str);
    }

    private static String toBase64(byte[] ba) {
        return DatatypeConverter.printBase64Binary(ba);
    }

    private static byte[] fromHex(String str) {
        return DatatypeConverter.parseHexBinary(str);
    }

    private static String toHex(byte[] ba) {
        return DatatypeConverter.printHexBinary(ba);
    }

    public PrivateKey getPrivateKey() {
        return privateKey;
    }

    public void setPrivateKey(PrivateKey privateKey) {
        this.privateKey = privateKey;
    }

    public PublicKey getPublicKey() {
        return publicKey;
    }

    public void setPublicKey(PublicKey publicKey) {
        this.publicKey = publicKey;
    }

    public ModeEnum getMode() {
        return mode;
    }

    public void setMode(ModeEnum mode) {
        this.mode = mode;
    }

    public DataTypeEnum getDataType() {
        return dataType;
    }

    public void setDataType(DataTypeEnum dataType) {
        this.dataType = dataType;
    }
}

In the above example, the class support writing cypher text in Base64 or Hex string format.

Usage:

TravisRsa travisRsa = new TravisRsa();
String encrypted = travisRsa.encrypt("This is plain text.");
String decrypted = travisRsa.decrypt(encrypted);
System.out.println("encrypted: " + encrypted);
System.out.println("decrypted: " + decrypted);

You could try encrypting in Java/Javascript side and then decrypting in another side.

Share this
Send this to a friend