2012-11-15 70 views
1

所以在node.js我有一個加密方案使用aes128,而不通過IV。示例如下Node.js aes128加密/解密端口到PHP

var cipher = require('crypto').createCipher('aes128','password'); 
cipher.update('test','utf8','base64')+cipher.final('base64'); 

其中輸出CjZ3R/tW8jiyLvg+/TE6bA==。問題是我不能在PHP中重現這一點,即使我已經嘗試了一堆實現和變體。

當我然後嘗試通過OpenSSL的運行此,我運行以下:

echo "test" | openssl enc -e -aes128 -a -k password 

其輸出U2FsdGVkX19Ccfv3SWvuzuZWeov9GDuwx1RMK2HWa/S =這也不匹配任一。我也嘗試過使用-md以及所有可能的選項,並且兩者都不匹配(它們甚至不是相同的塊大小)。在PHP中運行時,我嘗試使用填充來對密鑰/不使用哈希進行哈希處理,在輸入處使用計算的填充,其中填充的字符是所需填充字符的數量(在網上看到的東西表示這是nodejs使用的內容)。我已經嘗試將IV設置爲密碼,並且還嘗試將字節設置爲空,但仍然無法匹配。

在這裏的任何建議/想法?

編輯:

所以我剛剛發現在PHP函數openssl_encrypt並通過嘗試相同的測試,並再次得到了一個完全不同的輸出(這個現在採取完全相同的ARGS如Node.js和受他們理應既使用OpenSSL):

openssl_encrypt ("test" , 'aes128' , "password") 

其輸出(已用base64)JleA91MvYHdEdnj3KYHmog==其至少現在匹配塊計數,但仍然不一樣的密文。

我還應該提到的是,將IV傳遞給nodejs是一種選擇,它可能會解決這種差異,但是這種php方案將替換已存在的nodejs中的舊方案,因此它必須能夠解密已經創建的密文

+2

您是否檢查過OpenSSL和PHP是否都生成IV? – LMS

+0

我認爲他們都這樣做,而且無論我只是發現openssl_encrypt,我會期望這一個按預期工作,因爲它現在使用實際的aes128而不是MCRYPT_RIJNDAEL_128,但仍然不匹配 – user1084563

回答

5

所以我想出瞭解決方案。在查看node.js的C++源代碼後,我發現使用openssl函數EVP_BytesToKey生成密鑰和iv。在搜索這個函數的實現後,我發現這個堆棧溢出帖子Encrypting data in Cocoa, decoding in PHP (and vice versa)其中包含這個函數的一個版本。修改和補充說,OpenSSL的版本墊與ASCII字符等於需要填充的字節數的數據,我想出了以下功能充分匹配的NodeJS加密方案的事實:

function aes128Encrypt($key, $data) { 
    $padding = 16 - (strlen($data) % 16); 
    $data .= str_repeat(chr($padding), $padding); 

    $keySize = 16; 
    $ivSize = 16; 

    $rawKey = $key; 
    $genKeyData = ''; 
    do 
    { 
     $genKeyData = $genKeyData.md5($genKeyData.$rawKey, true); 
    } while(strlen($genKeyData) < ($keySize + $ivSize)); 

    $generatedKey = substr($genKeyData, 0, $keySize); 
    $generatedIV = substr($genKeyData, $keySize, $ivSize); 

    print($generatedIV); 
    print($generatedKey); 

    return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $generatedKey, $data, MCRYPT_MODE_CBC, $generatedIV); 
} 

它匹配與node.js函數完全一樣:

function aes128Encrypt(key,data) { 
     var cipher = require('crypto').createCipher('aes128',key); 
     return cipher.update(data,'utf8','binary')+cipher.final('binary'); 
}