2015-09-18 92 views
1

我试图解密使用OpenSSL的CryptoJS 3.1.5加密的文件。解密OpenSSL的AES与CryptoJS

一切工作正常,如果我加密和使用CryptoJS壳,这同样适用于OpenSSL的解密,但是当我尝试CryptoJS与OpenSSL的混合事事不顺心。

该文件使用此命令创建:

openssl enc -aes-256-cbc -in file.txt -out file.enc -k password 

,我尝试解密这样的:

fs.readFile('file.enc', function(err, data) { 
    var decrypted = CryptoJS.AES.decrypt(
        data.toString(), 
        "password", 
        { mode : CryptoJS.mode.CBC } 
       ); 

    console.log(decrypted.toString(CryptoJS.enc.Utf8)); 
}); 

// Give me this err: Uncaught Error: Malformed UTF-8 data 

而在其他的方式,我做的:

fs.readFile('file.txt', function(err, data) { 
    var encrypted = CryptoJS.AES.encrypt(
        data.toString(), 
        "password", 
        { mode : CryptoJS.mode.CBC }); 

    fs.writeFile('file.enc', encrypted); 
}); 

然后在Shell中:

openssl enc -d -aes-256-cbc -in file.enc -out file2.txt -k password 
// Give me this err: bad magic number 

我错过了一些明显的东西吗?

+0

你为什么要使用CryptoJS在node.js中是否有集成的'crypto'模块。另外,您正在使用哪个CryptoJS模块? –

+0

我需要CryptoJS 3.1.5 我遇到了使用nodejs加密模块的类似问题,如果需要,我可以发布更多示例代码。 – Tagada

+0

对不起,我使用这一个:https://www.npmjs.com/package/crypto-js – Tagada

回答

0

不是绝对还没有一个答案,但太多的评论:

命令行openssl enc默认使用基于密码的加密(PBE)盐,这意味着实际的加密密钥和IV应用时,它是对CBC ,根据给定密码和随机盐值由Password Based Key Derivation Function进行计算,这使对手更难以尝试猜测密码攻击。我不知道你的JS模块(或者多少JS),但是你链接的网页列出了各种低层原语,暗示它不会自动执行PBE。像“密码”这样的文本字符串(可能)适用于PBE,但不能直接进行AES加密,其中密钥必须是128,192或256位,并且应该是随机二进制数据。

如果你想要openssl的半标准PBE,在JS端匹配它;项目evpkey听起来可能有帮助,因为EVP是涉及的openssl模块,我不知道其他(PB)KDF方案将被称为EVP。如果不是,则enc默认的PBE就是密码的MD5,与盐串联在一起,根据需要迭代多次,在这种情况下是三次。有关(主要)perl中的示例,请参见https://superuser.com/questions/455463/openssl-hash-function-for-generating-aes-key。 OpenSSL将8个ASCII字符“Salted__”和8个字节的盐加到文件前,因此您需要在解密之前删除那些(并使用salt),或者在加密后添加它们。

如果你想原始加密,选择更适合的键(在哪一方),以及独特的和不可预测的IV,除非你总是使用在这种情况下,你可以使用一个固定的IV一个新的密钥,并在OpenSSL的侧面使用-K(注意大写)和-iv来指定这些值(十六进制)。请参阅安装了openssl的任何Unix系统的联机帮助页或https://www.openssl.org/docs/manmaster/apps/enc.html

在任一情况下加上enc默认为“PKCS#5”(确实是PKCS#7)填充。我不知道你的JS模块是否可以;如果不是,你应该指定它。除非你能保证你的明文永远是16字节的精确倍数(在像UTF8之类的编码之后);那么你可以在JS端指定(或者默认)没有填充,并在openssl端指定-nopad

+0

谢谢,那正是我寻找的那种信息。 我会用最终代码更新主要问题 – Tagada

+1

CryptoJS实际上以兼容OpenSSL的方式执行PBE,重新创建EVP_BytesToKey。这个问题可能是某种奇怪的编码问题,因为OP的代码应该工作。 –

2

这PHP代码,其中包括命令行OpenSSL的加密:

http://pastebin.com/sivmZvSw

......与此CryptoJS代码,我通常使用jsc在命令行中运行兼容我苹果:

http://pastebin.com/LcDBG7yj

(此代码编写与CryptoJS 3.1.2,虽然我不会期待和3.1.5之间的主要区别)

的招数是:

  1. 正如对方的回答表明,你需要指定确切的关键和四在双方为了它的工作。

  2. 尽管AES-256理论上可以处理128位密钥,但我发现只有256位密钥似乎可以工作。

  3. 在这些例子中,我避免使用salt值。通过添加盐,你可以证明它更安全,但要确保在两个地方都正确地指定它。

  4. 另一件让人感到意外的事情是他们认为他们只能将一个字符串传递给CryptoJS.decrypt()函数。这是不正确的。 CryptoJS.decrypt()需要一个cipherParams对象。 (请参见示例)。

  5. 关于填充:CryptoJSOpenSSL均默认为PKCS#7,除PKCS#7可处理任何块大小外,其功能等同于PKCS#5。当我们谈论8字节块大小时,它们是相同的。无论如何,你不需要在CrytoJS中指定填充。

祝你好运!

6

为了记录,这是我如何解密openssl文件。

//openssl enc -aes-256-cbc -in file.txt -out file.enc -k password 

fs.readFile('file.enc', function(err, data) { 
    var salt   = data.toString("hex", 8, 16), 
     enc   = data.toString("hex", 16, data.length), 
     derivedParams = CryptoJS.kdf.OpenSSL.execute(
         password, 
         256/32, 
         128/32, 
         CryptoJS.enc.Hex.parse(salt) 
        ), 
     cipherParams = CryptoJS.lib.CipherParams.create({ 
         ciphertext : CryptoJS.enc.Hex.parse(enc) 
        }), 
     decrypted  = CryptoJS.AES.decrypt(
         cipherParams, 
         derivedParams.key, 
         { iv : derivedParams.iv } 
        ); 

    console.log(hex2a(decrypted.toString())); // result is in hexa 
}); 

这就是我如何加密,使其与OpenSSL的工作

fs.readFile('file.txt', function(err, data) { 
    var encrypted = CryptoJS.AES.encrypt(data.toString(), password); 
     buff  = new Buffer(encrypted.toString(), "base64"); 

    fs.writeFile('file.enc', buff); 
}); 

// openssl enc -d -aes-256-cbc -in file.enc -out file2.txt -k password 

希望它会帮助别人:)

+0

这种方法是否支持openssl支持的'-salt'选项? – Jaap