AES加密中的CryptoJS额外参数。如何用PHP复制?

时间:2014-06-22 16:28:39

标签: javascript php encryption aes cryptojs

我试图用PHP 5.4.4复制以下CryptoJS 3.1.2代码:

var plaintext = 'test';
var key = CryptoJS.enc.Utf8.parse('9rIY8vV8DdOKx3m6JocjEaObhhYc2NfY');
var iv = CryptoJS.enc.Utf8.parse('r0dkbnVQhklNeUGA');
var encrypted = CryptoJS.AES.encrypt(plaintext, 'euhe68vjdr1aX4F091c7aCggSMBf0A7M', key,{iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});

我找到了几个处理该问题的问题,但是encrypt()plaintext之间的key都没有这个额外的参数。

CryptoJS wiki根本没有提到这个参数。 然而,它的确有效。我可以用这个来解密:

var decrypted = CryptoJS.AES.decrypt(encrypted, 'euhe68vjdr1aX4F091c7aCggSMBf0A7M', key, {iv: iv});

如果我在'euhe68vjdr1aX4F091c7aCggSMBf0A7M'电话中省略decrypt(),则无效。 所以这个参数确实做了些什么。但是什么?是哈希,盐吗?

有人知道如何用PHP复制这个特定的加密过程吗?

我无法以任何方式修改此JS代码。 代码位于登录页面上,用于在将凭据发送到服务器之前加密凭证。

我正在尝试使用PHP-cURL从命令行向该服务器提交凭据,这就是我需要重现此加密过程的原因。

更新:感谢Jim的回答,我现在有了正确的JavaScript,现在我需要帮助在PHP中复制代码

这是JS:

var plaintext = 'test';
var key = 'euhe68vjdr1aX4F091c7aCggSMBf0A7M';
var iv = CryptoJS.enc.Utf8.parse('r0dkbnVQhklNeUGA');
var encrypted = CryptoJS.AES.encrypt(plaintext, key, key,{iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7})

encrypted等于U2FsdGVkX1+ZujoXKqDHcO+4N1QO+Nv1KHUMFjZos1s=

这是解密:

var decrypted = CryptoJS.AES.decrypt(encrypted, key);

decrypted等于test

我尝试了许多不同的方法来使用PHP复制加密,但是它们都没有提供我可以使用上述JS解码的字符串。

例如,使用this AES_Encryption class,我尝试了以下代码:

$key = 'euhe68vjdr1aX4F091c7aCggSMBf0A7M';
$iv =  'r0dkbnVQhklNeUGA';
$message = 'test';
$AES              = new AES_Encryption($key, $iv, PKCS7);
$encrypted        = $AES->encrypt($message);
$decrypted        = $AES->decrypt($encrypted);
$base64_encrypted = base64_encode('Salted__'.$encrypted);

我最终得到U2FsdGVkX18eEv+TnigBEKGJL8t/V1Hm而不是U2FsdGVkX1+ZujoXKqDHcO+4N1QO+Nv1KHUMFjZos1s= 请注意,两个字符串以相同的方式启动,这要归功于我添加的'Salted__'前缀(因为CryptoJS似乎做同样的事情)。

我尝试了与phpseclib,openssl_encrypt和mcrypt相似的代码。没有运气。

任何暗示都会受到赞赏。

**更新:固定**

这个PHP代码完全匹配上面的CryptoJS代码。

function ssl_encrypt($pass, $data)
{
    // Set a random salt
    $salt = substr(md5(mt_rand(), true), 8);

    $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $pad = $block - (strlen($data) % $block);

    $data = $data . str_repeat(chr($pad), $pad);

    // Setup encryption parameters
    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, "", MCRYPT_MODE_CBC, "");

    $key_len =  mcrypt_enc_get_key_size($td);
    $iv_len =  mcrypt_enc_get_iv_size($td);

    $total_len = $key_len + $iv_len;
    $salted = '';
    $dx = '';
    // Salt the key and iv
    while (strlen($salted) < $total_len) {
        $dx = md5($dx.$pass.$salt, true);
        $salted .= $dx;
    }
    $key = substr($salted,0,$key_len);
    $iv = substr($salted,$key_len,$iv_len);

    mcrypt_generic_init($td, $key, $iv);
    $encrypted_data = mcrypt_generic($td, $data);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    //return chunk_split(base64_encode('Salted__' . $salt . $encrypted_data),32,"\r\n");
    return base64_encode('Salted__' . $salt . $encrypted_data);
}

function ssl_decrypt($password, $edata)
{
    $data = base64_decode($edata);
    print "Data: " . $data . "\n";

    $salt = substr($data, 8, 8);
    print "Salt (Base64): " . base64_encode($salt) . "\n";

    $ct = substr($data, 16);
    print "Content (Base64): " . base64_encode($ct) . "\n";

    $rounds = 3;
    $data00 = $password.$salt;

    print "Data00 (Base64): " . base64_encode($data00) . "\n";

    $md5_hash = array();
    $md5_hash[0] = md5($data00, true);

    $result = $md5_hash[0];
    print "MD5-Hash[0] (Base64): " . base64_encode($result) . "\n";
    for ($i = 1; $i < $rounds; $i++) {
        $md5_hash[$i] = md5($md5_hash[$i - 1].$data00, true);
        $result .= $md5_hash[$i];
        print "Result (Base64): " . base64_encode($result) . "\n";
    }

    $key = substr($result, 0, 32);
    print "Key (Base64): " . base64_encode($key) . "\n";
    $iv = substr($result, 32, 16);
    print "IV (Base64): " . base64_encode($iv) . "\n";

    print "Decrypted: " . openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv) . "\n";
}

$encryptedString = ssl_encrypt('euhe68vjdr1aX4F091c7aCggSMBf0A7M', 'test');
$decryptedString = ssl_decrypt('euhe68vjdr1aX4F091c7aCggSMBf0A7M', $encryptedString);

我不记得我在哪里找到它。遗憾。

1 个答案:

答案 0 :(得分:4)

这是一个JavaScript的东西,而不是CryptoJS的东西。试试这个:

var decrypted = CryptoJS.AES.decrypt(encrypted, 'euhe68vjdr1aX4F091c7aCggSMBf0A7M', {iv: iv});

或者这个:

key = 'euhe68vjdr1aX4F091c7aCggSMBf0A7M';
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {iv: iv});

你会看到你认为的关键,根本不是关键。它在最后与可选参数分组,然后丢失。

'euhe68vjdr1aX4F091c7aCggSMBf0A7M'是您的密钥,或者是您的密钥来源。