NodeJS unable to sucessfully decrypt C++ AES256 CBC string

78 Views Asked by At

Good evening all.

I have been trying to figure this out for literal days now but to no avail.

Situation:

  1. I am encrypting a string in C++ with OpenSSL's AES Lib. Then I am converting it to Base64 and sending it to my NodeJS Server for decryption.
  2. The JS server correctly recieves the encoded data, but always fails the decryption, no matter how I set things up, or change settings, ect
  3. I am using AES256 CBC
  4. The C++ encrypt function should be replicating the desired behaviour of PKCS#7 according to the documentation I have found about PKCS#7

Relevant code blocks:

C++ Code

#include <iostream>
#include <string>
#include <openssl/aes.h>
#include <openssl/rand.h>

#include "base64.h"

using namespace std;

// AES encryption key and IV (Initialization Vector)
const unsigned char aes_key[] = {
    "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
};

unsigned char aes_iv[] = {
    "0123456789abcdef0123456789abcdef"
};

string EncryptAES(const string& plainText) {
    AES_KEY enc_key;
    AES_set_encrypt_key(aes_key, 256, &enc_key);

    // Determine padding length
    int paddingLength = AES_BLOCK_SIZE - (plainText.length() % AES_BLOCK_SIZE);

    // If the plaintext length is already a multiple of the block size,
    // add a full block of padding
    if (paddingLength == 0) {
        paddingLength = AES_BLOCK_SIZE;
    }

    // Append padding bytes
    string paddedText = plainText;
    for (int i = 0; i < paddingLength; ++i) {
        paddedText.push_back((char)paddingLength);
    }

    // Encrypt padded plaintext
    string cipherText;
    cipherText.resize(paddedText.length());
    AES_cbc_encrypt((const unsigned char*)paddedText.c_str(), (unsigned char*)&cipherText[0], paddedText.length(), &enc_key, aes_iv, AES_ENCRYPT);

    return cipherText;
}

int main() {
    // Plain text message to encrypt
    string plainText = "Hello, this is a secret message.";

    // Encrypt the message using AES
    string encryptedText = EncryptAES(plainText);

    auto encodedText = base64_encode(encryptedText);

    std::cout << "Encoded text: " << encodedText << std::endl;

    return 0;
}

Base64 Lib Used

NodeJS Server

const express = require('express');
const bodyParser = require('body-parser');
const crypto = require('crypto');

const app = express();

// Middleware to parse JSON and URL-encoded bodies
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// AES decryption key and IV (Initialization Vector)
const aes_key = Buffer.from("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", 'hex');
const aes_iv = Buffer.from("0123456789abcdef0123456789abcdef", 'hex');

// AES decryption function
function DecryptAES(cipherText) {
    const decipher = crypto.createDecipheriv('aes-256-cbc', aes_key, aes_iv);
    let decrypted = decipher.update(cipherText, 'base64', 'utf8');
    decrypted += decipher.final('utf8');
    return decrypted;
}

app.post('/decrypt', (req, res) => {
    const { encryptedText } = req.body;

    if (!encryptedText) {
        return res.status(400).json({ error: 'Missing encryptedText in request body' });
    }

    try {
        const decryptedText = DecryptAES(encryptedText);
        res.send(decryptedText);
        console.log(decryptedText);
    } catch (error) {
        console.error('Decryption failed:', error);
        res.status(500).send('Decryption failed');
    }
});

const port = 3000;
app.listen(port, () => {
    console.log(`Server is running on http://localhost:${port}`);
});

My Question: Does anyone know what is happening? As far as I can tell, the encryption works perfectly, but the NodeJS refuses to correctly decode anything. I am unsure where my problem lays and have run out of options. Thanks all.

Behaviour:

  • When the server attempts to decrypt the key, it results a Bad Decrypt
  • If I use dicipher.setAutoPadding(false) it will incorrectly decrypt the string. (Will result in gibberish)
  • When I use an online AES decryptor the string from the C++ code works perfectly
  • Generating my own string (And encrypting ect) in NodeJS produces a different result to the C++ code (And websites)

Notes:

  • I am sending the POST request via Insomnia for testing. Sending the required JSON body with the below content.
  • I have a feeling the issue is related to how either the buffer is generated or decrypted, but none of my testing has produced any results so :/

JSON Body

{
    "encryptedText": "4oUys+a9EWvflSPZPxHYIfXcLV6wwisg7IlQ5a6Pa8CMkMiIwY2+ySMkQG351jJc"
}

Plain text = "Hello, this is a secret message." -> AES256_CBC -> Base64

0

There are 0 best solutions below