2012-08-22 69 views
1

由於某些奇怪的原因,Node內置的CipherDecipher類未按預期工作。該documentation指出cipher.updateNode.js Crypto AES密碼

「返回的加密內容,並且在其流可以被稱爲新的數據很多次了。」

docs還指出cipher.final

「返回任何剩餘的加密內容。」

然而,在我的測試中,你必須電話cipher.final獲取所有數據,從而使密碼對象毫無價值,並且處理您必須創建一個新的Cipher對象的下一個塊。

var secret = crypto.randomBytes(16) 
    , source = crypto.randomBytes(8) 
    , cipher = crypto.createCipher("aes128", secret) 
    , decipher = crypto.createDecipher("aes128", secret); 

var step = cipher.update(source); 
var end = decipher.update(step); 

assert.strictEqual(source.toString('binary'), end); // should not fail, but does 

注意,這個使用crypto.createCiphercrypto.createCipheriv時,與祕密的初始化向量發生。解決方法是,以取代線6和7用下列:

var step = cipher.update(source) + cipher.final(); 
var end = decipher.update(step) + decipher.final(); 

但對此,如前所述,使兩者cipherdecipher毫無價值。

這就是我期望Node內置的加密技術能夠工作的原理,但它顯然不適用。這是我如何使用它或Node中的錯誤的問題?或者我期待錯誤的事情?我可以直接執行AES,但這會很耗時和煩人。每次我需要加密或解密時,是否應該創建一個新的CipherDecipher對象?這看起來很昂貴,如果我這樣做是一個流的一部分。

回答

3

我遇到了兩個問題:第一個是我錯誤地認爲塊的大小是64位或8字節,這是我用來創建「明文」的原因。實際上,AES的內部將128位明文分成兩個64位塊,然後從那裏開始。

第二個問題是,儘管在應用上述更改後使用了正確的塊大小,crypto模塊正在應用自動填充,禁用自動填充解決了第二個問題。因此,工作示例如下:

var secret = crypto.randomBytes(16) 
    , source = crypto.randomBytes(16) 
    , cipher = crypto.createCipheriv("aes128", secret, secret); // or createCipher 
    , decipher = crypto.createDecipheriv("aes128", secret, secret); 

cipher.setAutoPadding(false); 
decipher.setAutoPadding(false); 

var step = cipher.update(source); 
var end = decipher.update(step); 

assert.strictEqual(source.toString('binary'), end); // does not fail 
+0

禁用填充是不安全的 –

+0

感謝您的提示。在上下文中,這並不重要,因爲我試圖在安全性不重要的環境中模擬安全系統的協議。 – skeggse

+0

is atuo padding salt –

2

AES使用16字節的塊大小(不是您建議的8倍)。而且,如果啓用了填充,它應該始終填充。其原因在於,否則,未壓縮算法無法區分填充和明文的最後一個字節。

大多數情況下,您不應該指望密文與純文本的大小相同。確保始終呼叫doFinal()。如果您正在實施自己的加密方案,則只應使用更新此方法進行加密/解密。

0

a node.js issue連續多次調用更新。我想這個問題已經解決,並在下一個版本中反映出來。