【问题标题】:Converting PHP encryption to NodeJS将 PHP 加密转换为 NodeJS
【发布时间】:2021-01-30 13:29:23
【问题描述】:

我目前正在对我的 API 实施加密。我必须以与在 PHP 编写的特定脚本中加密和解密相同的方式实现这一点。

当我将结果输出为base64 时,一切正常。 PHP 解密方法针对它运行并且工作得很好。问题是,由于某些要求,我需要输出的不是base64而是二进制,但是当我从Nodejs端加密成二进制时,结果与我在PHP中加密成二进制时的结果不同,但它应该是相同的。

PHP 加密:

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 加密:

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;
}

【问题讨论】:

  • 您为什么期望输出“相同”?它们不能相等,因为您使用的是(coorectly)随机 iv,它们必须有所不同。其次 - PHP 代码正在计算您的 node.js 代码中缺少的身份验证值(“HMAC”)。

标签: php node.js encryption binary base64


【解决方案1】:

我已经稍微更新了您的代码以接受 iv 参数。您可以使用与以前相同的方式生成它(例如 openssl_random_pseudo_bytes)。

出于演示的目的,我将使用固定的 IV,以便我们可以显示相同的结果。

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"));

在这种情况下,结果将如下所示:

PHP:

结果(BASE64):eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5 + o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG + 6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw + aCwsnIV1h0 =

Node.js:

结果(BASE64):eQMrc61Gt8qRejRjhJOkVxsqZTqUjSUnaL46yZDLGGK5 + o7WKLyIiG4UKj0ST93Wi7UlaAyTFIjpIs0C893SFsnHeuVshG + 6EJF99GrLSUCMFJG3J1pJnmxF4Pu8ZCbN7Ounp0BjhJKIpu9yQn6uEYylJLXWpzNw + aCwsnIV1h0 =

【讨论】:

  • 但我认为他说的是相等的二进制结果,因为他说在 base64 中输出与预期的一样,但是当他尝试以二进制输出它们时,它们并不像预期的那样相等
  • 嗯..很好的观察。我会等待 OP 审核后再更新!
猜你喜欢
  • 2020-07-31
  • 1970-01-01
  • 2019-06-06
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多