2016-11-19 67 views
1

我想實現一個PHP加密腳本到JavaScript中。我的PHP腳本返回一個128個字符的字符串,而我的基於Javascript的返回160個字符。基於JavaScript的版本的前128個字符與基於PHP的版本匹配。Javascript AES加密返回太多字符

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串lenght。我正在使用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版本的輸出是

86b1c9874069129d0852eade01eb753a176a1c6155c4af3ac447ae0a5350b92c3447f95be9c4f8cdbf14503696bcaa16e6307c1605a2cac503239db9d1ac6fb33051208849788f8a90db1cbe2494cac7

+0

什麼輸出是什麼樣子? – Sammitch

+0

輸出已添加到問題 – Robbert

+0

最好不要使用mcrypt的,它已經現在放棄的近十年。因此它已被棄用,並將在PHP 7.2中從核心和PECL中刪除。它不支持標準的PKCS#7(néePKCS#5)填充,只有非標準的null填充甚至不能用於二進制數據。 mcrypt有很多優秀的[bug](https://sourceforge.net/p/mcrypt/bugs/)可以追溯到2003年。相反,考慮使用[defuse](https://github.com/defuse/php-encryption)或者[RNCryptor](https://github.com/RNCryptor),他們提供了一個完整的解決方案,正在維護和正確。 – zaph

回答

1

額外的32個字符是16字節的十六進制編碼,這是填充。 Java是添加填充,PHP不是。

注意mcrypt的不使用標準PKCS#7(姓PKCS#5)填充。

好的加密庫將有一個填充選項並添加加密填充,並刪除它解密。你不應該做你自己的填充。