2016-03-25 239 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 [...]' 我喜欢这个标记作为正确的评论,但是现在上面的片段,我不希望其他任何人遇到这个问题并且有同样的问题。 –