Encryption and Decryption

Generate the keys

  • openssl genrsa -out mykey.pem 2048
  • openssl rsa -in mykey.pem -pubout > public_key.pem
  • openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in mykey.pem -out private_key.pem

doEncrypt

importPackage(java.io);
importPackage(java.util);
importClass(java.util.Base64);
importClass(java.security.cert.CertificateFactory);
importClass(java.security.cert.X509Certificate);
importClass(java.security.KeyStore);
importClass(java.security.spec.X509EncodedKeySpec);
importPackage(java.security);
importPackage(java.security.interfaces);
importPackage(java.security.spec);
importPackage(Packages.javax.crypto);
importPackage(Packages.javax.crypto.interfaces);
importPackage(Packages.javax.crypto.spec);
importPackage(Packages.javax.security.cert);

var JString = java.lang.String;

function doEncrypt ( password, file )
{
  try
  {
    var varCheck = (checkRegex ( password, "^.+$") );
    myFile = new File (file)
    key = new JString(Files.readAllBytes(myFile.toPath()));
  }
  catch (e)
  {
    return ( new JString() );
  }

  publicKey = key.replace("-----BEGIN PUBLIC KEY-----", "").replaceAll(System.lineSeparator(), "").replace("-----END PUBLIC KEY-----", "");

  encoded = Base64.getDecoder().decode(publicKey);

  keyfactory = KeyFactory.getInstance("RSA");
  keySpec = new X509EncodedKeySpec(encoded);

  publicKey = keyfactory.generatePublic(keySpec);
  encrypt_cipher = Packages.javax.crypto.Cipher.getInstance("RSA");
  encrypt_cipher.init(Packages.javax.crypto.Cipher.ENCRYPT_MODE, publicKey);

  ciphertext = encrypt_cipher.doFinal(new JString(password).getBytes());

  var encoded = Base64.getEncoder().encodeToString(ciphertext).getBytes();
  return ( new JString(encoded) );
}

var varCerts = new Array();
varCerts.push ( "./public_key.pem" );
varCerts.push ( "./private_key.pem" );

var varPassword = "MyPassword";
varEncrypted = doEncrypt ( varPassword, varCerts[0] );

doDecrypt

importPackage(java.io);
importPackage(java.util);
importClass(java.util.Base64);
importClass(java.security.cert.CertificateFactory);
importClass(java.security.cert.X509Certificate);
importClass(java.security.KeyStore);
importClass(java.security.spec.X509EncodedKeySpec);
importPackage(java.security);
importPackage(java.security.interfaces);
importPackage(java.security.spec);
importPackage(Packages.javax.crypto);
importPackage(Packages.javax.crypto.interfaces);
importPackage(Packages.javax.crypto.spec);
importPackage(Packages.javax.security.cert);

var JString = java.lang.String;

function doDecrypt ( password, file )
{
  try
  {
    myFile = new File (file);
    key = new JString(Files.readAllBytes(myFile.toPath()));
  }
  catch (e)
  {
    return ( new JString() );
  }

  privateKey = key.replace("-----BEGIN PRIVATE KEY-----", "").replaceAll(System.lineSeparator(), "").replace("-----END PRIVATE KEY-----", "");

  encoded = Base64.getDecoder().decode(privateKey);
  keyfactory = KeyFactory.getInstance("RSA");
  keySpec = new PKCS8EncodedKeySpec(encoded);

  privateKey = keyfactory.generatePrivate(keySpec);

  decrypt_cipher = Packages.javax.crypto.Cipher.getInstance("RSA");
  decrypt_cipher.init(Packages.javax.crypto.Cipher.DECRYPT_MODE, privateKey);

  try
  {
    decoded = Base64.getDecoder().decode(password);
    ciphertext = decrypt_cipher.doFinal(decoded);
    return ( new JString(ciphertext) );
  }
  catch (e)
  {
    return ( new JString() );
  }
}

var varCerts = new Array();
varCerts.push ( "./public_key.pem" );
varCerts.push ( "./private_key.pem" );

var varPassword = "Ou0b5H7ha/sVfqK+gA2hCPhs7c8qeGSTKkMAcyCH2vSjb8CfvfeE8d+NbDwzveYPxC4Rh5GNR0CiQaAZPIiIqV4DMv/i2ELhcjPeI9VWloX5OMrMa5VVoyWElRh93N+D1XP7j+N9ogxRstObLQS1C+uczFmLDEIkWvwNdEM8O7DdkKvgaULiw4r4kfV3ROM0Uu44hxsFTp8V3pIR9ncrkK27ZEE4SGsd1BtimxACNgzqc3fGXxICU4VRDgP0oSSHO35d8ouHt8raAmdVWfKFYqaIWgP9/RSmooHTCaQBfb1tCCLxXrEkEZa47bTIXyIs2I4pBc02OGrDdNMQtAbUWA==";
varDecrypted = doDecrypt ( varPassword, varCerts[1] );

As an example, I have wrapped the doEncrypt and doDecrypt functions in a separate class.
Notice that the two encrypted values are different, due to the fact that the values to encrypt are encrypted using a Public Key.

./doClassM.sh –encrypt
Please enter the value to encrypt :
myPassword$
Value to encrypt : myPassword$
Encrypted value : Gcr+uPEZ2F7prfiF4+YihrOhan4D+CaIBDYILep7xtMMOpBZAUtOC0+gPDunFI6QAGFFFYBa2gnwUySxTDDxJsSp++XwwFFJb7MMA9TjuYJXFdCCiE7EZNIwnTI7fniO0eYJi7VOyN4eB9Wb6wCNj6ug4ZRBMJFTphj+N6ukK8WQSmJUg8yLifnc3zn4d6Vz7uP7D2lGofeK2VTkOVuWN8TZbaMvqI+flCP5Ed8yUzr8hfDqCfTJ8KlAHKXGQDlidg0uBrC8DA9/nPisUi6h7cx4uM+hTbNnOO7r/FyadUCOFsIfcQXMs3iEOlGS1J53/jaDOn03XkVf/1jah71yMA==
Decrypted value : myPassword$

./doClassM.sh –encrypt
Please enter the value to encrypt :
myPassword$
Value to encrypt : myPassword$
Encrypted value : eKUVpeJxsr5jUkfZq78k/zeC1vaFvORpSzkszzQYuK8tUwP0/FikM1Vr7wx34EZh+0ho3ByztZ11btYPOASiQpgHCa+TXwB6nVce4uSwuKfqqGOXaW9wpiR/R5roORr3LULkdPuU1a22JkYjziEDmjVF24CKtXOsoeZhxLwZV6VAN/v+4I2erBs5OqI+aDczsvCtnQ3vFL8kE7l6iDdYktZ6vlKtuX7CKsh22Qu9lHjtFzGSZ1P5XQVtDGXYgrkT+h6pkrw9dzVIhLgdfPf4rkfTzMTMfj0TdwbeOWsK9o5UMha64TAweUR1ZGcj/aLat+bQCqdufBkHsbNamakKqQ==
Decrypted value : myPassword$

The encrypted value can be safely stored in a configuration file, and if the decryption code and the private key are both secure you are safe in the knowledge that the actual values behind the encrypted ones are safe.

I use Mozilla Rhino for all my cross-platform code projects, and I compile the source code in to a Java class file.

#!/bin/bash

java -cp "lib/*" org.mozilla.javascript.tools.jsc.Main -nosource -d out doDecrypt.js

The code inside the Java class file cannot be viewed, even with a Java JAR de-compiler, so I therefore know that my code is safe from prying eyes.