Spike - NodeJS and Java metadata encryption
Overview
This guide demonstrates how to encrypt and decrypt data in NodeJS and Java.
Encryption algorithm
The encryption algorithm used in the examples is aes-256-cbc.
This algorithm requires both a key and an initialization vector in order to encrypt and decrypt the message.
Initialization Vector (IV)
An initialization vector (or IV) are used to ensure that the same value encrypted multiple times, even with the same secret key, will not always result in the same encrypted value. This is an added security layer.
It is recommendable to generate a new IV on each call in order to use a distinct ciphertext on each encryption.
NodeJS
Encrypt example
const crypto = require('crypto');
const ALGORITHM = 'aes-256-cbc';
const AES_KEY = "bD9X2wydyRT96sDH+kWctET3z50zsxhw+00hV0yCRnc=";
// TODO: Fixed IV for testing
const AES_IV = "iJ4qSZ3f0Z70UXzdiZmVAw==";
// TODO: Fixed IV for testing purposes. A random IV should be generated on each call and shared
// along with encripted data, it can be public.
// const iv = crypto.randomBytes(16);
const iv = Buffer.from(AES_IV, 'base64');
// TODO: Remove log
console.log("IV: " + iv.toString('base64'));
// Code to generate key
// const key = crypto.randomBytes(32);
// const string_key = key.toString('base64');
// console.log("key: "+ string_key);
const encrypt = (plainString) => {
const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(AES_KEY, 'base64'), iv);
const encrypted = Buffer.concat([cipher.update(plainString, "utf8"), cipher.final()]);
return encrypted.toString('base64');
}
var encrypted = encrypt("Hello World!");
// TODO: Remove log
console.log("Encrypted Text: " + encrypted);
Decrypt example
const decrypt = (base64String, iv) => {
let decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(AES_KEY, 'base64'), iv);
const deciphered = Buffer.concat([decipher.update(Buffer.from(base64String, 'base64')), decipher.final()]);
return deciphered.toString("utf8");
}
const decrypted = decrypt(encrypted, iv)
// TODO: Remove log
console.log("Decrypted Text: " + decrypted);
Java
Encrypt example
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
public class CipherTest {
private static final String ALGORITHM = "AES/CBC/PKCS5PADDING";
private static final String AES_KEY = "bD9X2wydyRT96sDH+kWctET3z50zsxhw+00hV0yCRnc=";
// TODO: Fixed IV for testing purposes.
private static final String AES_IV = "iJ4qSZ3f0Z70UXzdiZmVAw==";
public static String encrypt(String input) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
SecretKeySpec key = new SecretKeySpec(Base64.getDecoder().decode(AES_KEY), "AES");
// TODO: Fixed IV for testing purposes. A random IV should be generated on each call and shared
// along with encripted data, it can be public.
// IvParameterSpec iv = generateIV();
IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(AES_IV));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] cipherText = cipher.doFinal(input.getBytes());
String encryptedText = Base64.getEncoder().encodeToString(cipherText);
// TODO: Remove log
System.out.println("Encrypt: "+encryptedText);
return encryptedText;
}
public static IvParameterSpec generateIV() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
// TODO: Remove log
System.out.println("IV: "+Base64.getEncoder().encodeToString(iv));
return new IvParameterSpec(iv);
}
}
Decrypt example
public static String decrypt(String cipherText) throws NoSuchPaddingException, NoSuchAlgorithmException,
InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
SecretKeySpec key = new SecretKeySpec(Base64.getDecoder().decode(AES_KEY), "AES");
// TODO: Fixed IV for testing purposes. A random IV should be generated on each call and shared
// along with encripted data, it can be public.
// IvParameterSpec iv = generateIV();
IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(AES_IV));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] plainText = cipher.doFinal(Base64.getDecoder().decode(cipherText));
String decryptedText = new String(plainText);
// TODO: Remove log
System.out.println("Decrypt: "+decryptedText);
return decryptedText;
}