Encrypt data using AES algorithm with CryptoJS

Looking to implement AES encryption in JavaScript using the AES/CBC/NoPadding Mode and a method to complete 16-length blocks. Successfully solved this task using Java, here is an example:

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-length 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);
}

When using

key = 253D3FB468A0E24677C28A624BE0F939
, strToEncrypt = "My Secret text", and ceros IV as inputs, the output will be:

7StScX3LnPUly/VNzBes0w==

The desired output has been achieved successfully! However, I attempted to replicate this in JavaScript using the CryptoJs library but failed to produce the same result as in Java. Here is what I tried:

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 resulted in De+CvPVIyiBX2//EE6gXTg== being produced instead of the expected output 7StScX3LnPUly/VNzBes0w==. Any insights on what might be going wrong or how to achieve the same result as in Java would be greatly appreciated. Thank you!

Answer №1

Considering that you will address issues like the empty IV and treating this as a prototype, your code fails due to the following reasons:

  1. No padding is used in Java, which needs to be replicated in JS.
  2. You manually add nulls for padding in Java, which must also be done in JS.
  3. The key is base64 decoded but actually consists of a hexadecimal string of bytes.
  4. In Java, the IV contains nulls while in JS it uses whitespace treated as base64.

To achieve the same 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());

Resulting in:

7StScX3LnPUly/VNzBes0w==

Answer №2

To encrypt with a custom Initialization Vector (IV), follow these steps...

    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 finalEncryptedText = encrypted.iv+':'+encrypted.ciphertext

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Find similarities and differences between two CSV files

Dealing with 2 large files, both exceeding 1 million rows: The first file contains only an md5 hash The second file contains pairs of md5 and email addresses My task is to compare these two files and if the md5 hashes match, write the corresponding emai ...

Resultant vector

Having trouble calculating the resultant of 3 vectors. Every time I input a number, it returns NaN. Can someone shed some light on this? var vector1 = document.getElementById("f1"); var vector2 = document.getElementById("f2"); var vecto ...

Verify if the textbox is empty

Is there a way to verify that the input field with type "text" is not empty before moving to the next page? <input TYPE="text" name="textbox2" align="center"> ........ function HomeButton() { <!--if both textbox1 and textbox2 values are not ...

Ways to Determine if the Content in the CKEditor has Been Altered

Is there a way to detect changes in the content of CKEditor? I want to trigger a JavaScript function every time the content is updated. ...

Setting a default value for a prop function in VueJS

How can a default function be set for a prop with the type of function? props: { clickFunction: { type: 'Function' default: ???? } } ...

Changing Marker Colors in OpenLayers After Importing GPX Data: A Quick Guide

Check out this link for a code tutorial on importing GPX files and displaying map markers. I successfully implemented this code to show map markers. Is there a way to customize the color of the markers? Edit: var fill = new Fill({ color: 'rgba(2 ...

Trouble with Slides.js jQuery plugin loading properly on Chrome and Safari, works perfectly on Firefox

I have implemented a slideshow plugin from on my website: . The issue I am facing is with its compatibility in different browsers. When viewed in Firefox, the slideshow functions perfectly as expected. However, in Chrome or Safari, the slideshow fails to ...

Issue with useEffect function not loading correctly in Gatsby production environment

I'm currently in the process of building a website with Gatsby.js. Within my component, I've incorporated animations using Gsap within the useEffect function. During debugging, everything works as expected. However, once the site is in productio ...

Should we consider packaging the npm dependencies code along with our code as a best practice?

What is the best way to handle npm dependencies in our code bundle? If it's preferable to include the npm dependency code in our bundle, does it make sense to add it as a separate module or package? If not, how can I prevent bundling my dependencie ...

Automated Desk: adjust page through programming

I am currently utilizing Smart Table and I would like to automatically navigate to a specific page once the controller has been created and the table is displayed. After searching on stackoverflow, I came across this code snippet that allows me to achieve ...

Creating a HTML and JavaScript carousel without relying on the animate function

I am currently facing some challenges with building a custom slider. While it moves forward smoothly using CSS animation, I'm struggling to implement a backward motion with an animation. It seems like I need to loop through the slides and try a differ ...

Describe the feasible choices for the columns in Hibernate

Is it possible to restrict the column values to a specific set while saving Enums in Hibernate? Can this be accomplished through annotations? Alternatively, is it possible to create custom annotations, such as: @possibleValues({"LIKE","COMMENT","SHARE"}) ...

Exploring the world of Next.js version 9.3 and beyond with the exciting addition

As a beginner with Next.js, I am seeking guidance on utilizing getStaticPaths and getStaticProps within catch-all routes. Many blog starters for Next.js 9.3+ focus on single-level blog posts (such as /posts/post-1.md, /posts/post-2.md, etc.), but I am stru ...

Enable tabber upon clicking on the navigation bar

Hello there, I am facing an issue with my website's navigation. I have a navigation bar with the unique id #nav and I want to activate a specific tab based on the clicked navigation list item. The HTML structure of the navigation #nav looks like this: ...

Tips for refreshing a webpage after returning from a redirected page

After utilizing certain logic, I am able to redirect to a new page. return RedirectToAction("Index"); If I navigate back to the previous page using the browser's back button, I would like for the "old" page to automatically update with default valu ...

Unleashing the power of eventListeners through exponential re-rendering upon state updates

Trying to implement an eventListener for "keydown" to update the state (a boolean named showMenu). I placed it inside a useEffect, but it's not functioning correctly and I can't pinpoint the issue. When I include showMenu in the dependency arra ...

Utilize a Vue.js filter on the v-model within an input element

Seeking assistance! I successfully created a directive that wraps the Jasny Bootstrap Plugin, specifically focusing on the input mask feature! Additionally, I have developed a custom filter using moment to format date fields! The date format received fro ...

The form within the dynamically loaded AJAX content is malfunctioning

My webpage is set up to load content from a separate file (content.php) into a div and refresh it every 5 seconds. In the content.php file, I have a form (basic HTML without javascript) that works fine when accessed directly at (example.com/content.php). ...

Whenever I refresh my website after deployment, I encounter an empty error using the MERN stack

Here is a question I previously posted: How can I properly use the res.sendFile for my MERN APP, as I encounter an error every time I refresh, and it was resolved there. I encountered a similar issue here, even after following the same steps that worked b ...

Exploring ways to pass props in functional components in React Native

I am currently exploring how to create an API in React Native with TypeScript without using the class extends component. However, I am struggling to figure out how to access and send props from one const view to another function: App.tsx import React, {us ...