Javascript AES 加密返回太多字符

Javascript AES Encryption returning too many characters

我正在尝试将 PHP 加密脚本实施到 JavaScript 中。我的 PHP 脚本 returns 一个 128 个字符的字符串,而我的 Javascript 基于一个 returns 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 returns 160 个字符和前 128 个匹配我的 PHP 脚本。

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

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

我哪里错了?

编辑 PHP版本的输出是

86b1c9874069129d0852eade01eb753a176a1c6155c4af3ac447ae0a5350b92c3447f95be9c4f8cdbf14503696bcaa16e6307c1605a2cac503239db9d1ac6fb3[=16]

JavaScript版本的输出是

86b1c9874069129d0852eade01eb753a176a1c6155c4af3ac447ae0a5350b92c3447f95be9c4f8cdbf14503696bcaa16e6307c1605a2cac503239db9d1ac6fb33051208849788f8a90db1cbe2494cac7

额外的32个字符是16字节的十六进制编码,也就是填充。 Java 正在添加填充,PHP 不是。

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

好的加密库会有一个填充选项,加密时添加填充,解密时删除。您不必自己填充。