Transforming Python AES into Node JS

I've encountered a challenge trying to make existing legacy Python code encrypt/decrypt data the same way as NodeJS. Although the first 16 characters are correctly decoded, I'm facing issues with the rest of the process.

Here's the Python code snippet:

from Crypto.Cipher import AES
counter = b'HOJFKGQMRCTKUQHP'
cipher = AES.new(self.symmetric_key, AES.MODE_CTR, counter=lambda: counter)
encrypted = cipher.encrypt(data)

While researching, I came across a resource mentioning that the same counter is used in every iteration: PyCrypto problem using AES+CTR

Contrastingly, here is what works in NodeJS (ts-node) only for the first 16 characters:

import { createDecipheriv, Decipher } from 'crypto'
const decrypt = (inputBase64: string): string => {
    const algorithm = 'aes-192-ctr'; // 24 byte key, 16 byte "counter"
    var decipher: Decipher = createDecipheriv(algorithm, key, counter /* yes, it's an iv */)
    return decipher.update(inputBase64, 'base64', 'utf8') + decipher.final('utf8');
}

Browsing through multiple sources online, I noticed that most implementations increment the counter - can the counter increment be controlled using the built-in Node crypto library? Perhaps overriding some methods could help resolve this matter. Here are examples I found which might offer clues: https://github.com/ricmoo/aes-js/blob/master/index.js#L656 https://github.com/brix/crypto-js/blob/develop/src/mode-ctr.js#L26

Is there any way I can make this work in Node environment properly without altering my legacy Python code and preserving existing data integrity?

encrypt('Testing--StackOverflow')
# outputs: 'r7G8gFNIHuY27nBjSo51nZ6mqZhVUQ=='

When attempting decryption in Node utilizing the above decrypt function:

const key = 'LKOXBRRUNBOSMENKEPPZUKWB';
const counter = 'HOJFKGQMRCTKUQHP';
const encrypted = 'r7G8gFNIHuY27nBjSo51nZ6mqZhVUQ==';
const clearText = decrypt(encrypted);
console.log('clear text:', clearText)
// outputs: clear text: Testing--StackOv�::��m

If anyone has insights or solutions to offer on this perplexing issue, I would greatly appreciate it!

Answer №1

The essential element of the CTR mode is the incrementing counter, hence its name - "counter" mode. The Python code provided in this example does not properly implement CTR mode as it uses a constant counter instead of incrementing it, making it insecure and non-functional.

Most libraries are designed to prevent such misuse of the CTR mode, therefore it is unlikely to find a library in NodeJS or any other language that allows intentional vulnerability.

However, decryption in NodeJS (or any other language) can still be achieved by manually implementing the mode. In CTR mode, a byte sequence is generated from the Initialization Vector (IV) by appending the incremented IV for each block, which is then encrypted with AES and XOR-ed with the plaintext/ciphertext. Although the Python code skips the incrementation step, decryption can still be accomplished through manual implementation:

const crypto = require('crypto');

var algorithm = 'aes-192-ecb';
var key = Buffer.from('LKOXBRRUNBOSMENKEPPZUKWB', 'utf8'); 
var byteSeq = Buffer.from('HOJFKGQMRCTKUQHPHOJFKGQMRCTKUQHP', 'utf8'); 
var ciphertext = Buffer.from('r7G8gFNIHuY27nBjSo51nZ6mqZhVUQ==', 'base64');

// Encrypt the byte-sequence generated from the IV (no incrementation)
var cipher = crypto.createCipheriv(algorithm, key, null);
var byteSeqEnc = Buffer.concat([cipher.update(byteSeq), cipher.final()], byteSeq.length);

// XORing of ciphertext and IV
var decrypted = xor(ciphertext, byteSeqEnc);
console.log("Decrypted: " + decrypted.toString('utf8'));
// Output: Decrypted: Testing--StackOverflow 

// Implementation of XOR
function xor(buf1, buf2){
    var buf = Buffer.alloc(buf1.length);
    for (i = 0; i < buf1.length; i++){
        buf.writeUInt8(buf1.readUInt8(i, i + 1) ^ buf2.readUInt8(i, i + 1), i);
    }
    return buf;
}

The length of the byte sequence should match the length of the plaintext/ciphertext rounded up to an integer multiple of the blocksize. In this example, the byte sequence has been hard-coded to be 32 bytes for simplicity.

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

Sending requests from a React application to a Node.js backend hosted on an Nginx server with SSL enabled

After creating static files for a reactjs app using the create react app tool, I launched an nginx server on a docker container to serve the front end built with reactjs. This nginx server communicates with a node js in another container. Everything was r ...

Employing asynchronous operations and the power of async/await for achieving seamless integration

I am currently facing an issue where I need to retrieve queries from a database stored in Postgres. A function is utilized, which employs a callback mechanism. In order to fetch rows from the database, there exists a function called getRecipesByCategoryFo ...

When performing a mutation in GraphQL with Mongoose, properties are set to null if the argument is not passed

To simplify this example as much as possible, let's consider a basic Schema with an embedded GraphQLObjectType: const nameType = new GraphQLObjectType({ name: 'NameType', fields: { first: new GraphQLNonNull(GraphQLString), last: ...

Node.JS driver encounters limitations with the $and operator in MongoDB during bulk updates

I've been experimenting with the Bulk update API in MongoDB 3.0.4 using Node.js when I encountered an unexpected error. It seems that whenever I use operators like $and or $ne, I get the error message shown below. However, simple queries appear to wor ...

Retrieving the most recent data in a Dask dataframe with duplicate dates in the index column

Although I'm quite familiar with pandas dataframes, Dask is new to me and I'm still trying to grasp the concept of parallelizing my code effectively. I've managed to achieve my desired outcomes using pandas and pandarallel, but now I'm ...

The deletion process simply adds a question mark to the existing URL and does not actually remove the blogpost

I've been working on a small blog application using Node and Express. Strangely, when trying to delete a blog post, clicking the submit button adds a "?" into the link as shown here: http://prntscr.com/gizmvu After thoroughly reviewing my code, I&apo ...

Sending JSON information from a template to a Django view

In my table, I have an attribute value with a CHAR data type. I am trying to post string data from an HTML template that I obtained from an HTTP GET request using AngularJS. However, when I click the submit button, I receive the following error: `ValueE ...

Develop a query language using Python

I'm seeking a method to make filtering capabilities accessible to fellow developers and potentially clients within my workplace. Challenge I aim to introduce a basic query language for my data (stored as python dicts) that can be used by other devel ...

Is AngularJS primarily a client-side or server-side framework, or does it have elements

Is it possible to connect to the database on the server side? I have experience using it on the client side, but can the same method be used on the server side? If it's not suitable for server-side use, should I go with PHP or Node.js for designing ...

Using Node.js and Express.js to redirect users after a successful data insertion

I am currently developing a CRUD application in Nodejs/Expressjs using EJS as the templating engine. Within my "views" folder, I have created a subfolder named "login" which contains several .ejs files. All of my .ejs files are located within the views fo ...

The output of server.address() method in Node.js is ::

My memory serves me right, a few days back it was showing "localhost". I'm puzzled as to what altered server.address().address to now return double colons (::). According to my research, it seems to be returning an IPv6 address (::) because it's ...

Is there a way to set up IIS to host my NodeJS REST API on a unique URL without having to expose any additional ports?

Recently, my organization provided me with a Windows Server running Windows Server 2019 and IIS. I have successfully configured PHP and MySQL to host my website on this server using IIS. However, I have now developed a new service using Node.js that serve ...

What could be causing the error "Err: user.validPassword is not a function" to occur

I am in the process of developing a node.js app and I have implemented Passport js. After referring to the Passport-local documentation on their official website, I decided to utilize the local passport-strategy. However, I encountered an error stating tha ...

Are you currently utilizing an unconventional "NODE_ENV" value within your environment settings? Discover how to easily configure the default value of NODE_ENV in a Windows operating system

Recently, I modified the value of NODE_ENV to production using the command: setx NODE_ENV production However, whenever I execute npm run dev or build in my Nextjs project, I encounter an error message saying: You are using a non-standard "NODE_ENV" value ...

What could be causing the AttributeError message stating that the 'Contact' object does not have the 'print_entry' attribute?

I need assistance with my code. I was told not to alter anything below the print_directory function. Above that, I have created the contact class. However, I am encountering an attribute error. Can you help me understand why this is happening and how I can ...

Is there a way to implement material-ui autocomplete based on the initial input field selected or entered by users?

I am looking to implement two input fields, one for selecting a country and the other for selecting a school. Is there a way to have autocomplete functionality based on the country selected? For example, if a user selects Dublin as the country, only scho ...

Looking for the submit button amongst the elements

I'm currently working on developing a Steam bot using Python that is intended to post within a Steam group. However, I am facing difficulties with the final phase as I am unable to locate the submit button. <button type="submit" class="btn_green_w ...

Utilizing URL parameters to send data to a Python CGI script

My goal is to pass parameters into my cgi script in order to display a specific post when a URL like www.helloworld.com/cgi-bin/world.py?post=101 is entered. I've attempted the following: link = '<a href="world.py?post=%s">test</a>& ...

Scrapy spider encountering issues during the crawling process

Having trouble crawling coupons on the Cuponation website. Whenever I try to run the crawler, it shows an error. Can someone please assist me? Thanks. import scrapy from scrapy.http import Request from scrapy.selector import HtmlXPathSelector from scrap ...

Increment field(s) conditionally while also performing an upsert operation in MongoDB

I need to perform an insert/update operation (upsert) on a document. In the snippet below, there is a syntactical error, but this is what I am attempting to achieve: $inc: { {type=="profileCompletion"?"profileCompletion":"matchNotification"}: 1}, If the ...