Good evening all.
I have been trying to figure this out for literal days now but to no avail.
Situation:
- 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.
- The JS server correctly recieves the encoded data, but always fails the decryption, no matter how I set things up, or change settings, ect
- I am using AES256 CBC
- The C++ encrypt function should be replicating the desired behaviour of
PKCS#7according 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;
}
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