【问题标题】:Decrypt Crypto-js encrypted text with key with PHP使用 PHP 用密钥解密 Crypto-js 加密文本
【发布时间】:2020-12-10 21:22:10
【问题描述】:

我正在使用 Crypto-js 使用密钥加密密码并将其发送到服务器。我想使用 PHP 在服务器中解密它。如何做到这一点?

JS:

  let encKey = "Secret Passphrase"; 
  let text = "123";
  let iv = CryptoJS.enc.Hex.parse("FgLFXEr1MZl2mEnk");
  var encryptedText = CryptoJS.AES.encrypt(text, encKey, { iv: iv }).toString();

加密文本:

U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=

PHP:

<?php
$strg  =  "U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=";
$encryptedstrings  =  base64_decode($strg);
$encryptionMethod  =  'aes-256-cbc';
$key  =  "Secret Passphrase";
$iv  =  "FgLFXEr1MZl2mEnk";
  
$rawText   = openssl_decrypt($encryptedstrings, $encryptionMethod, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING , $iv);

var_dump($rawText);

结果:

string(32) "����>���s����V?E��M���I"

我在这里得到了奇怪的结果。

【问题讨论】:

  • 你没有通过$iv in.
  • 我传入了 $iv,仍然得到错误的数据。 (编辑问题)
  • 目前您在 CryptoJS 代码中不使用 key,而是使用 password。要使用 32 字节密钥(对于 AES-256),您必须传递 WordArray,例如CryptoJS.enc.Utf8.parse("01234567890123456789012345678901")。关于 IV,使用了错误的解析器。 Utf8 编码器可以使用 16 字节的 IV,例如CryptoJS.enc.Utf8.parse("FgLFXEr1MZl2mEnk")。在 PHP 代码中必须使用 PKCS7 填充,即必须删除 OPENSSL_ZERO_PADDING 标志。
  • @Topaco 当我删除 OPENSSL_ZERO_PADDING 标志时,它返回 false。可以举个例子吗?
  • 您不仅必须更改标志,还必须修复其他错误,如我的评论中所述。如果您想使用问题中所述的密钥,则必须将密钥作为WordArray 传递。如果要使用密码,则必须将其作为字符串传递。不过我不推荐后者,因为应用了不安全的密钥派生函数。

标签: javascript php encryption openssl cryptojs


【解决方案1】:

以下解决方案不是来自我,而是来自@Artjom B.,所以所有功劳归他所有。您将在此处找到来源:https://stackoverflow.com/a/27678978/8166854

对于您的问题:您使用 密码 而不是密钥运行 CryptoJs 加密。根据文档 (https://cryptojs.gitbook.io/docs/#the-cipher-algorithms) 部分的密码算法,(内部 AES)密钥是从密码短语派生而来的,该密码短语具有不应再使用的过时且不安全功能。

Artjom B. 能够使这个密钥派生在 PHP 上可用。作为旁注:没有必要提出一个 加密函数的初始化向量 (IV),因为 IV 也是从密码短语派生的,所以我将其保留 在下面的代码中。

这是 PHP 端的结果:

solution for https://stackoverflow.com/questions/65234428/decrypt-crypto-js-encrypted-text-with-key-with-php
string(3) "123"
decryptedtext: 123

这是代码,请遵守警告: 提供此代码是为了实现不同编程语言之间的兼容性。它不一定是完全安全的。它的安全性取决于密码的复杂性和长度,因为只有一次迭代和使用 MD5。我建议使用至少 20 个字符的密码,最好是随机生成的字母数字字符。

<?php

/*
source: https://stackoverflow.com/a/27678978/8166854 author: Artjom B.
Security notice: This code is provided for achieve compatibility between different programming languages.
It is not necessarily fully secure. Its security depends on the complexity and length of the password,
because of only one iteration and the use of MD5. I would recommend to use at least a 20 character password
with alphanumeric characters which is ideally randomly generated.
 */

function evpKDF($password, $salt, $keySize = 8, $ivSize = 4, $iterations = 1, $hashAlgorithm = "md5") {
    $targetKeySize = $keySize + $ivSize;
    $derivedBytes = "";
    $numberOfDerivedWords = 0;
    $block = NULL;
    $hasher = hash_init($hashAlgorithm);
    while ($numberOfDerivedWords < $targetKeySize) {
        if ($block != NULL) {
            hash_update($hasher, $block);
        }
        hash_update($hasher, $password);
        hash_update($hasher, $salt);
        $block = hash_final($hasher, TRUE);
        $hasher = hash_init($hashAlgorithm);
        // Iterations
        for ($i = 1; $i < $iterations; $i++) {
            hash_update($hasher, $block);
            $block = hash_final($hasher, TRUE);
            $hasher = hash_init($hashAlgorithm);
        }
        $derivedBytes .= substr($block, 0, min(strlen($block), ($targetKeySize - $numberOfDerivedWords) * 4));
        $numberOfDerivedWords += strlen($block)/4;
    }
    return array(
        "key" => substr($derivedBytes, 0, $keySize * 4),
        "iv"  => substr($derivedBytes, $keySize * 4, $ivSize * 4)
    );
}

function decrypt($ciphertext, $password) {
    $ciphertext = base64_decode($ciphertext);
    if (substr($ciphertext, 0, 8) != "Salted__") {
        return false;
    }
    $salt = substr($ciphertext, 8, 8);
    $keyAndIV = evpKDF($password, $salt);
    $decryptPassword = openssl_decrypt(
        substr($ciphertext, 16),
        "aes-256-cbc",
        $keyAndIV["key"],
        OPENSSL_RAW_DATA, // base64 was already decoded
        $keyAndIV["iv"]);
    return $decryptPassword;
}

echo 'solution for https://stackoverflow.com/questions/65234428/decrypt-crypto-js-encrypted-text-with-key-with-php' . PHP_EOL;
$key  =  "Secret Passphrase";
$strg = "U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=";
$rawText = decrypt($strg, $key);
var_dump($rawText);
echo 'decryptedtext: ' . $rawText . PHP_EOL;
?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-12
    • 2014-10-24
    • 2020-11-24
    • 2023-03-17
    • 2012-04-11
    • 2014-02-06
    相关资源
    最近更新 更多