2016-03-25 240 views
1

所以我有一段代碼用密碼加密字符串。它使用CryptoJS AES加密功能(CryptoJS.AES.encrypt)和看起來像這樣...解密Forge.js中的CryptoJS AES數據(帶密碼短語)

CryptoJS.AES.encrypt(data, password).toString(); 

展望未來,我不想使用CryptoJS,因爲它正式棄用/不維護,我反而喜歡使用Forge.js。我試圖通讀GitHub上的Forge.js文檔來找到解決方案,但一直未能找到任何使用密碼而不是手動創建密鑰的密碼。

我在https://code.google.com/archive/p/crypto-js/採取看看CryptoJS存檔,似乎如果encrypt函數傳遞一個字符串作爲第二個參數(密鑰)它作爲密碼導出密鑰和IV。但它沒有詳細說明它是如何做到這一點的。

看來,base64解碼的結果給出了一個字符串開頭Salted__然後一個逗號,然後加密的二進制文本blob,我不確定我將如何通過「鹽」通過僞造。

我該如何去解密這個使用Forge.js的數據blob?

回答

4

CryptoJS支持OpenSSL的EVP_BytesToKey函數,該函數通過一輪MD5從新生成的salt和密碼派生出密鑰和IV。有對forge documentation page一個例子:

使用Node.js的開拓,以配合OpenSSL的「ENC」命令行工具 (注: OpenSSL的「ENC」使用非標準文件格式的自定義鍵 推導函數和爲1的固定迭代計數,其中一些 考慮比等替代的OpenPGP/GnuPG的)安全性較低的:

var forge = require('node-forge'); 
var fs = require('fs'); 

// openssl enc -des3 -in input.txt -out input.enc 
function encrypt(password) { 
    var input = fs.readFileSync('input.txt', {encoding: 'binary'}); 

    // 3DES key and IV sizes 
    var keySize = 24; 
    var ivSize = 8; 

    // get derived bytes 
    // Notes: 
    // 1. If using an alternative hash (eg: "-md sha1") pass 
    // "forge.md.sha1.create()" as the final parameter. 
    // 2. If using "-nosalt", set salt to null. 
    var salt = forge.random.getBytesSync(8); 
    // var md = forge.md.sha1.create(); // "-md sha1" 
    var derivedBytes = forge.pbe.opensslDeriveBytes(
    password, salt, keySize + ivSize/*, md*/); 
    var buffer = forge.util.createBuffer(derivedBytes); 
    var key = buffer.getBytes(keySize); 
    var iv = buffer.getBytes(ivSize); 

    var cipher = forge.cipher.createCipher('3DES-CBC', key); 
    cipher.start({iv: iv}); 
    cipher.update(forge.util.createBuffer(input, 'binary')); 
    cipher.finish(); 

    var output = forge.util.createBuffer(); 

    // if using a salt, prepend this to the output: 
    if(salt !== null) { 
    output.putBytes('Salted__'); // (add to match openssl tool output) 
    output.putBytes(salt); 
    } 
    output.putBuffer(cipher.output); 

    fs.writeFileSync('input.enc', output.getBytes(), {encoding: 'binary'}); 
} 

// openssl enc -d -des3 -in input.enc -out input.dec.txt 
function decrypt(password) { 
    var input = fs.readFileSync('input.enc', {encoding: 'binary'}); 

    // parse salt from input 
    input = forge.util.createBuffer(input, 'binary'); 
    // skip "Salted__" (if known to be present) 
    input.getBytes('Salted__'.length); 
    // read 8-byte salt 
    var salt = input.getBytes(8); 

    // Note: if using "-nosalt", skip above parsing and use 
    // var salt = null; 

    // 3DES key and IV sizes 
    var keySize = 24; 
    var ivSize = 8; 

    var derivedBytes = forge.pbe.opensslDeriveBytes(
    password, salt, keySize + ivSize); 
    var buffer = forge.util.createBuffer(derivedBytes); 
    var key = buffer.getBytes(keySize); 
    var iv = buffer.getBytes(ivSize); 

    var decipher = forge.cipher.createDecipher('3DES-CBC', key); 
    decipher.start({iv: iv}); 
    decipher.update(input); 
    var result = decipher.finish(); // check 'result' for true/false 

    fs.writeFileSync(
    'input.dec.txt', decipher.output.getBytes(), {encoding: 'binary'}); 
} 

此示例示出了用於三重DES,但它以相同的方式工作爲AES。你只需要將ivSize更改爲16.

+0

我很欣賞它,這是我的問題的答案。我忽略了能夠重複使用AES引用的3DES示例。 –

+0

我意識到我在嘗試了您的建議後沒有回覆。也許我錯過了一些東西,但是'ivSize'只是簡單地將'3DES'改爲'AES'並將'8'改成'16'不會產生相同的結果。我試圖尋找問題的可能性,因爲僞造說它是成功的,但輸出是完全不同的 - 所以我不知道它是否是一個編碼相關的問題?不太確定。 –

+0

鍛造輸出以下字符串... '1pÍ0¿UÚ@G4WtCÕ5¸«ñZ¿} A6©_ͬiñýü¾¸iÔú®ð5ÕÆÉP¹ú)nQOW»AMO 3 {〜5 = O!¼=W²Ò? [...]' 凡爲cryptojs輸出以下... '----- BEGIN RSA私鑰----- MIIEowIBAAKCAQEAqSFulewpMjRBLhiiorbvWleD5I [...]' 我喜歡這個標記作爲正確的評論,但是現在上面的片段,我不希望其他任何人遇到這個問題並且有同樣的問題。 –