【问题标题】:Javascript AES Encryption returning too many charactersJavascript AES加密返回太多字符
【发布时间】:2017-04-02 23:12:43
【问题描述】:

我正在尝试在 JavaScript 中实现 PHP 加密脚本。我的 PHP 脚本返回 128 个字符的字符串,而我的基于 Javascript 的脚本返回 160 个字符。基于 JavaScript 的版本的前 128 个字符与基于 PHP 的版本匹配。

function pkcs5_pad ($text, $blocksize){
  $pad = $blocksize - (strlen($text) % $blocksize);
  return $text . str_repeat(chr($pad), $pad);
}
$skey = "somekey";
$ivKey = "someIVKey";
$input = "empid=xxxxxx;timestamp=Sat, 19 Nov 2016 00:33:03 UTC";

try {
  $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128,'cbc');
  echo strlen($input) . "\n";
  $input = pkcs5_pad($input, $size);
  echo strlen($input) . "\n";
  $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');

  $key = pack('H*', $skey);
  $iv = pack('H*', $ivKey);
  # The key size used is 16, 24 or 32 bytes - for AES-128, 192 and 256 respectively

  if (mcrypt_generic_init($cipher, $key, $iv) != -1){
    $encrypted = mcrypt_generic($cipher, $input);
    mcrypt_generic_deinit($cipher);
    $encryptedString = bin2hex($encrypted);
  }
  echo $encryptedString . "\n";
  echo strlen($encryptedString) . "\n";
} catch (Exception $ex) {
  echo $ex->getMessage();
}

strlen($encryptedString) 这里的长度是 128 个字符。

我的基于 JavaScript 的版本使用 CryptoJS 创建如下所示的外观

var aesKey = "somekey";
var ivKey = "someIVKey";

function pkcs5_pad (text, blocksize){
  console.log(text.length);
  var pad = blocksize - (text.length % blocksize);
  console.log("pad:" + pad);
  return text + str_repeat(chr(pad), pad);
}

input = "empid=xxxxxx;timestamp=Sat, 19 Nov 2016 00:33:03 UTC";

var size = 16;
console.log(input.length);
var input = pkcs5_pad(input, size);
console.log('"' + input + '"');
console.log(input.length);

var key = CryptoJS.enc.Hex.parse(aesKey);
var iv = CryptoJS.enc.Hex.parse(aesIV);

var encryptedString = CryptoJS.AES.encrypt(input,key,{iv: iv});
console.log(encryptedString.ciphertext.toString().length);
encryptedString = encryptedString.ciphertext.toString();

所有内容都匹配,包括 pkcs5_pad 之前和之后的字符串长度。我正在使用来自 locutus.io 的一些附加 JavaScript 代码来调用 str_repeat 和 chr。这里encryptedString.ciphertext.toString().length 返回 160 个字符,前 128 个字符与我的 PHP 脚本匹配。

我的理解是 CryptoJS 的第 3 版使用 CBC 模式,但我也将模式明确设置为 CBC 无济于事。我还将加密字符串返回为十六进制

encryptedString = encryptedString.ciphertext.toString(CryptoJS.enc.Hex);

我哪里错了?

编辑 PHP版本的输出是

86b1c9874069129d0852eade01eb753a176a1c6155c4af3ac447ae0a5350b92c3447f95be9c4f8cdbf14503696bcaa16e6307c1605a2cac503239db9d1ac6fb3

JavaScript 版本的输出是

86B1C9874069129D0852ADE01EB753A176A1C6155C4AF3AC447AE0A5350B92C3447F95BE9C4F8CA5350B92C3447F4503696BCAA2CAC503239DB9D1C603239DB9D1C203239DB9D1C20323952CA2CACH603239DB9D1C2032394CAC7 P>

【问题讨论】:

  • 输出是什么样的?
  • 输出已添加到问题中
  • 最好不要使用mcrypt,它已经废弃了近十年了。因此,它已被弃用,并将在 PHP 7.2 中从核心中删除并进入 PECL。它不支持标准 PKCS#7 (née PKCS#5) 填充,仅支持甚至不能用于二进制数据的非标准空填充。 mcrypt 有许多出色的 bugs 可以追溯到 2003 年。请考虑使用 defuseRNCryptor,它们提供了完整的解决方案,正在维护并且是正确的。
  • 是的,我没有使用 mcrypt。我得到了 PHP 代码,并想用 JavaScript 实现它,因为它在我们的环境中效果更好。

标签: javascript php encryption mcrypt cryptojs


【解决方案1】:

额外的 32 个字符是 16 个字节的十六进制编码,即填充。 Java 增加了 padding,PHP 没有。

请注意,mcrypt 不使用标准 PKCS#7(née PKCS#5)填充。

良好的加密库将具有填充选项,并在加密时添加填充并在解密时将其删除。你不应该自己做填充。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-22
    • 2020-11-21
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多