Different result for AES-256-GCM between PHP openssl_encrypt and TypeScript Crypto

97 Views Asked by At

I try to migrate the encoding by aes-256-gcm in PHP to NodeJS, but they generate the different results as following:

PHP example:

<?php

function Encrypt(string $data = "", string $merKey = "", string $merIV = "")
{
    $tag = ""; // default empty
    $encrypted = openssl_encrypt($data, "aes-256-gcm", trim($merKey), 0, trim($merIV), $tag);

    return trim(bin2hex($encrypted . ":::" . base64_encode($tag)));
}

// For example
$data = "exampleData";
// Secret
$merKey = "12345678901234567890123456789012";
$merIV  = "1234567890123456";

$encryptStr = Encrypt($data, $merKey, $merIV);
print_r($encryptStr);
// 4d38727078724f39655347563066513d3a3a3a5a46415a536c374a35326c36513344655833754768413d3d
?>

NodeJS example (written in TypeScript):

import { createCipheriv } from "crypto";

let authTag: Buffer;

class SymmetricEncryptor {
  private readonly algorithm = "aes-256-gcm";
  private readonly secretKey: Buffer;
  private readonly iv: Buffer;

  public constructor(strKey: string, strIV: string) {
    this.secretKey = Buffer.from(strKey);
    this.iv = Buffer.from(strIV);
  }

  public encrypt(original: Buffer): Buffer {
    const cipher = createCipheriv(this.algorithm, this.secretKey, this.iv);
    let cipherText = cipher.update(original);
    cipherText = Buffer.concat([cipherText, cipher.final()]);
    authTag = cipher.getAuthTag();

    return Buffer.concat([
      cipherText,
      Buffer.from(":::"),
      Buffer.from(authTag.toString("base64"))
    ]);
  }
}

const merKey = "12345678901234567890123456789012";
const merIV = "1234567890123456";
const symmetricEncryptor = new SymmetricEncryptor(merKey, merIV);

let data = "exampleData";
const encryptedData = symmetricEncryptor.encrypt(
  Buffer.from(data, "utf-8")
);
console.log(encryptedData.toString('hex'));
// 33cae9c6b3bd792195d1f43a3a3a5a46415a536c374a35326c36513344655833754768413d3d

The encoding data after ::: is correct, but it seems to be different before :::. I found that the issue could be from padding settings in TypeScript but I don't know how to fix it, because I change the options in openssl_encrypt from 0 to 3 and they are produce the same result. However, I cannot change the behavior in PHP. How can I change the code in NodeJS above to generate the same result as in PHP?

0

There are 0 best solutions below