【问题标题】:I tried crypto-js but the output is not correct, please see my code and correct me where I am wrong我尝试了 crypto-js 但输出不正确,请查看我的代码并纠正我的错误
【发布时间】:2021-04-15 10:47:46
【问题描述】:

我的后端有一个 simple_crypt 函数,它工作正常,现在我想要为 javascript 创建一个与 php 完全相同的函数。 所以我研究并得到了 CryptoJS 库,与 PHP 相比,我的“Key”和“iv”值是正确的,但是当我加密我的字符串时,输出完全不同。

这是我的工作 PHP 代码,我想将其转换为 javascript。

<?php 

 function simple_crypt( $string ) {

  $secret_key = '1234567890';
  $secret_iv = '0987654321';
  $output = false;
  $encrypt_method = "AES-256-CBC"; 
  $key = hash( 'sha256', $secret_key );
  $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );

  echo "Key : ".$key."<br>";
  echo "iv : ".$iv."<br>";

  $output = openssl_encrypt( $string, $encrypt_method, $key, 0, $iv );

  return $output;
 }


   $e =  simple_crypt("text");
   echo $e;
   echo "<br>";


?>

这是我遇到问题的 JS 代码,请查看并告诉我此 js 代码哪里错了。

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js" integrity="sha512-nOQuvD9nKirvxDdvQ9OMqe2dgapbPB7vYAMrzJihw5m+aNcf0dX53m6YxM4LgA9u8e9eg9QX+/+mPu8kCNpV2A==" crossorigin="anonymous"></script>
 <script type="text/javascript">

function simple_crypt(string) {

    var secret_key, secret_iv, output, key, iv;

    secret_key = '1234567890';
    secret_iv = '0987654321';
    output = false;

   

    key = CryptoJS.SHA256(secret_key).toString();
    iv = CryptoJS.SHA256(secret_iv).toString().substr(0, 16);

    console.log("key",key);
    console.log("iv",iv);


      var encrypted = CryptoJS.AES.encrypt(string, key, {iv: iv});
      return (encrypted.toString());
}

console.log(simple_crypt("text"));

</script>

这是输出:
PHP:T4F65n4AVlmkkb5LLFhRIQ==
JS:U2FsdGVkX18HJGpPYZPm6crBcxA7TfbZZ9Sc/4qHGBk=

【问题讨论】:

  • 这里是 PHP 的输出:T4F65n4AVlmkkb5LLFhRIQ==
  • JS : U2FsdGVkX18HJGpPYZPm6crBcxA7TfbZZ9Sc/4qHGBk=

标签: javascript php encryption hash cryptojs


【解决方案1】:

为了使两个代码产生相同的结果,NodeJS 代码中的 key 和 IV 必须与 PHP 代码中的相同,并以WordArrays 传递。为此,您生成的密钥和 IV 必须进一步处理如下:

key = CryptoJS.enc.Utf8.parse(key.substr(0, 32));
iv = CryptoJS.enc.Utf8.parse(iv);

在 PHP 代码中,SHA256 哈希作为十六进制字符串返回。使用十六进制编码,字节数加倍,即 SHA256 散列是十六进制编码的 64 个字节。 PHP 隐式 只考虑 AES-256 密钥的前 32 个字节,即忽略最后 32 个字节。在 CryptoJS 代码中,这必须显式地发生(对于 IV,这会发生,但对于密钥,这是缺失的)。
通过使用 UTF8 编码器解析,将 key 和 IV 转换为WordArrays。如果密钥作为字符串传递(如问题中发布的代码),则 CryptoJS 将该值解释为密码并使用密钥推导函数来推导密钥和 IV(这与 PHP 代码中的逻辑不兼容) .

通过上述更改,CryptoJS 代码给出与 PHP 代码相同的结果:

function simple_crypt(string) {

    var secret_key, secret_iv, output, key, iv;

    secret_key = '1234567890';
    secret_iv = '0987654321';
    output = false;

    key = CryptoJS.SHA256(secret_key).toString();
    iv = CryptoJS.SHA256(secret_iv).toString().substr(0, 16);

    key = CryptoJS.enc.Utf8.parse(key.substr(0, 32));
    iv = CryptoJS.enc.Utf8.parse(iv);

    console.log("key",key.toString());
    console.log("iv",iv.toString());

    var encrypted = CryptoJS.AES.encrypt(string, key, {iv: iv});
    return (encrypted.toString());
}

console.log(simple_crypt("text")); // T4F65n4AVlmkkb5LLFhRIQ==
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"&gt;&lt;/script&gt;

请注意以下几点:

  • 使用 SHA256 从密码中获取密钥是不安全的。为此,应使用可靠的密钥派生函数,例如 PBKDF2。
  • 出于安全原因,密钥/IV 对只能应用一次。因此,IV 通常是为每次加密随机生成的。 IV 不是秘密,通常与密文(通常在前面)一起发送给接收者。或者,可以使用 KDF(结合随机生成的盐)与密钥一起导出 IV。

【讨论】:

  • 感谢 Topaco 的大力帮助,您的解决方案如我所愿。
  • 真心感谢
猜你喜欢
  • 2020-10-31
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 2016-04-02
  • 1970-01-01
  • 2021-04-22
  • 2016-10-21
  • 1970-01-01
相关资源
最近更新 更多