I need to implement AES encryption using JavaScript. Used AES/CBC/NoPadding Mode and created a method to complete 16 lenght blocks. I already solved it using Java. It looks like:
public static String encrypt(byte[] key, byte[] initVector, String value) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(completeBlocks(value));
return Base64.encodeBase64String(encrypted);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException ex) {
System.out.println("Error: " + ex);
}
return null;
}
/**
* Completes 16 lenght blocks
*
* @param message
*
*
*/
static byte[] completeBlocks(String message) {
try {
int bytesLenght = message.getBytes("UTF-8").length;
if (bytesLenght % 16 != 0) {
byte[] newArray = new byte[bytesLenght + (16 - (bytesLenght % 16))];
System.arraycopy(message.getBytes(), 0, newArray, 0, bytesLenght);
return newArray;
}
return message.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
System.out.println("" + ex);
}
return null;
}
public static void main(String[] args) {
String key = "253D3FB468A0E24677C28A624BE0F939";
String strToEncrypt = "My Secret text";
final byte[] initVector = new byte[16];
String resultado = encrypt(new BigInteger(key, 16).toByteArray(), initVector, strToEncrypt.trim());
System.out.println("ENCRYPTED:");
System.out.println(resultado);
}
With inputs key = 253D3FB468A0E24677C28A624BE0F939
, strToEncrypt = "My Secret text"
and ceros IV. It throws
7StScX3LnPUly/VNzBes0w==
I Know it's the desired output. It's right! I tried to replicate this using JavaScript. I used CryptoJs library. But i wasn't able to produce same Java's output. I have tryed:
var text = "My Secret text";
var key = CryptoJS.enc.Base64.parse("253D3FB468A0E24677C28A624BE0F939");
var iv = CryptoJS.enc.Base64.parse(" ");
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv});
console.log(encrypted.toString());
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {iv: iv});
console.log(decrypted.toString(CryptoJS.enc.Utf8));
Using the same inputs, i get De+CvPVIyiBX2//EE6gXTg==
as output. What am I doing wrong? How can i get same Java's output? Thanks a lot!!
CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key. DES is a previously dominant algorithm for encryption, and was published as an official Federal Information Processing Standard (FIPS).
CryptoJS is a growing collection of standard and secure cryptographic algorithms implemented in JavaScript using best practices and patterns. They are fast, and they have a consistent and simple interface.
If you want to encrypt using custom IV, then you can encrypt like...
let iv = CryptoJS.lib.WordArray.random(IV_LENGTH);
const key = CryptoJS.enc.Utf8.parse(ENCRYPTION_KEY);
let encrypted = CryptoJS.AES.encrypt(text, key, { iv })
const encrypted = encrypted.iv+':'+encrypted.ciphertext
Assuming you will fix things like the empty IV & that this is a proof of concept, your code fails because:
To duplicate the output in JS:
CryptoJS.pad.NoPadding = {pad: function(){}, unpad: function(){}};
var text = "My Secret text\0\0";
var key = CryptoJS.enc.Hex.parse("253D3FB468A0E24677C28A624BE0F939");
var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv, padding: CryptoJS.pad.NoPadding});
console.log(encrypted.toString());
For:
7StScX3LnPUly/VNzBes0w==
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With