1

I'm currently implementing encryption on my API. I have to implement this the same way it is encrypted and decrypted in a specific script written in PHP.

This works all fine when I output the result in, let's say, base64. The PHP decrypt method runs against it and works just fine. The problem is that I need to output not in base64 but in binary due to certain requirements, but when I encrypt from the Nodejs side into binary the result is different than when I encrypt in the PHP into binary when it should be the same.

PHP Encryption:

function vd_encrypt($plaintext, $password) {
$method = "AES-256-CBC";
$key = hash('sha256', $password, true);
$iv = openssl_random_pseudo_bytes(16);

$ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
$hash = hash_hmac('sha256', $ciphertext, $key, true);

return $iv . $hash . $ciphertext;

}

Javascript Encryption:

import crypto from 'crypto';

export function encrypt (plain_text: string): string {
    const encryptionMethod = 'AES-256-CBC';
    const iv = crypto.randomBytes(IV_LENGTH);
    const key = crypto.createHash("sha256").update(secret).digest();

    var encryptor = crypto.createCipheriv(encryptionMethod, key, iv);

    const result = iv + encryptor.update(plain_text, 'utf8', 'binary') + encryptor.final('binary');

    return result;
}
1
  • 1
    Why do you expect that outputs will be "the same"? They can't be equal because you are using a (coorectly) random iv to they have to differ. Second - the PHP-code is calculating an authentication value ("HMAC") that is missing in your node.js code. Commented Oct 16, 2020 at 6:46

1 Answer 1

4

I've updated your code slightly to accept an iv parameter. You can generate this in the same way as before (e.g. openssl_random_pseudo_bytes).

For the purposes of demonstration I'll use a fixed IV so we can show the same result.

PHP

function vd_encrypt($plaintext, $password, $iv) {
    $method = "AES-256-CBC";
    $key = hash('sha256', $password, true);
    $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
    $hash = hash_hmac('sha256', $ciphertext, $key, true);
    return $iv . $hash . $ciphertext;
}

// Replace with below code in production
// $iv = openssl_random_pseudo_bytes(16);
$iv = base64_decode("eQMrc61Gt8qRejRjhJOkVw==");
$result = vd_encrypt("He was a man take him for all in all, I shall not look upon his like again", "password", $iv);

echo "Result (base64): " . base64_encode($result) . "\n";

Node.js

import crypto from 'crypto';

export function encrypt (plaintext: string, password: string, iv: string): string {
    const encryptionMethod = 'AES-256-CBC';
    const key = crypto.createHash("sha256").update(password).digest();
    const encryptor = crypto.createCipheriv(encryptionMethod, key, iv);

    const encryptedData = Buffer.concat([encryptor.update(plaintext, 'utf8'), encryptor.final()]);
    const hash = crypto.createHmac("sha256", key).update(encryptedData).digest();

    return Buffer.concat([iv, hash, encryptedData]);
}

// Replace with below code in production 
//const iv = crypto.randomBytes(16);
const iv = Buffer.from("eQMrc61Gt8qRejRjhJOkVw==", "base64");
const result = encrypt("He was a man take him for all in all, I shall not look upon his like again", "password", iv);
console.log("Result (base64):", result.toString("base64"));

In this case the results will be like so:

PHP:

Result (base64): eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5+o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG+6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw+aCwsnIV1h0=

Node.js:

Result (base64): eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5+o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG+6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw+aCwsnIV1h0=
Sign up to request clarification or add additional context in comments.

2 Comments

But i think he was talking in a equal binary result, since he stated that in base64 the outputs were as expected, but when he tried to output them in binary they werent equal as expected
Hmmm.. good observation. I'll wait for the OP to review before I update!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.