2017-02-11 84 views
1

我加密使用AES 128 CBC與一個空白IV和密鑰字符串「aaaaaaaaaaaaaaaa」(16字節UTF8字符串)(16 0的),並獲得不同的結果加密結果的不同之處PHP和Node.js的

在PHP中:

echo base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,pack("H*", "00000000000000000000000000000000"),"aaaaaaaaaaaaaaaa",MCRYPT_MODE_CBC,pack("H*", "00000000000000000000000000000000"))) 

返回 「kmwP6gWv1l9ZMdKanGs/NA ==」

中的Node.js:

let cipher = require('crypto').createCipheriv('aes-128-cbc',Buffer.alloc(16),Buffer.alloc(16)) 
console.log(cipher.update('aaaaaaaaaaaaaaaa','utf8','base64') + cipher.final('base64')) 

返回 「kmwP6gWv1l9ZMdKanGs/N HeUidae8Z4dK0HU7p2z + 1C =」

的第一比特(粗體)等同於PHP,但PHP值有一個額外的 'A =' 然後節點值具有整個額外「HeUidae8Z4dK0HU7p2z + 1c'

我承認我對這裏發生的事很不自在 - 我在這裏錯過了什麼?

編輯 ...但並不那麼不穩定,我不明白,我在這裏做的是不是特別安全。不要擔心這是否是進行加密的「正確」方式 - 請注意結果應該一致的事實。

EDIT2 - 我可以,但是,接近使用十六進制,而不是的base64 -

PHP:926c0fea05afd65f5931d29a9c6b3f9c

節點:926c0fea05afd65f5931d29a9c6b3f9c 779489d69ef19e1d2b41d4ee9db3fb57

節點十六進制的第二塊被退回通過.final方法,我不明白它是什麼。

+0

我不知道它是否相關,但是https://www.base64decode.org/只適用於第二個字符串,如果選擇ASCII。 – apokryfos

+1

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

回答

4

AES適用於16字節的塊大小。您正在加密字符串「hello world」,它是UTF8中的11個字節長。因此,填充用於將字符串的長度增加到16個字節。

節點和它應該使用PKCS5填充將純文本填充到16個字節然後對其進行加密。

mcrypt,因爲它不應該,使用零字節填充您的純文本。 mcrypt是已棄用並已放棄十年。

由於您的兩個填充方案不同,在我們應用AES之前,純文本實際上是不同的。

我的建議:使用PHP中的openssl_*函數代替。並且不要使用靜態IV。使用靜態IV會使您的程序容易受到與ECB模式相同的漏洞影響,這不太好!

+0

即使採用靜態IV(壞主意),CBC模式也不會遭受與ECB模式相同的可玩性(一個非常糟糕的主意)。 CBC模式不會顯示[企鵝效應](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29),向下滾動到企鵝。 – zaph

+0

你是對的,但靜態的IV仍然會導致明文恢復攻擊。也許我應該選擇更好的話。將編輯。 –

+0

「因爲你的兩個填充方案是不同的,所以在我們甚至到達應用AES的點之前,純文本實際上是不同的。」 - 好吧,我認爲這很有道理。 –

相關問題