【问题标题】:Encryption Program That Works With NodeJs and mbedtls适用于 NodeJs 和 mbedtls 的加密程序
【发布时间】:2016-09-19 00:53:30
【问题描述】:

首先,让我先声明一下,我无论如何都不是密码学家,而且我也不是很擅长编写 c 代码,所以如果这个问题的答案是显而易见的或得到了回答,请原谅。我正在开发一个消息传递程序,无法在目标平台上使用 TLS。因此,我需要找到一种方法来使用对称预共享密钥密码(如 AES)来加密每条消息。

我正在寻找一种方法来加密和解密一端的 mbedtls 程序(例如 aescrypt2)和另一端的 nodejs 程序之间的数据。 Mbedtls,以前称为 polarssl,是一个为嵌入式设备提供加密的库。源代码中包含一些示例程序,例如 aescrypt2、rsaencrypt、ecdsa 和 crypt_and_hash。

Aescrypt2 在生成的加密数据也使用 aescrypt2 解密时工作正常,但我似乎无法使用 aescrypt 加密数据以使用 nodejs 加密或任何其他程序解密,包括 openssl。例如:

echo 'this is a test message' >test.txt
aescrypt 0 test.txt test.out hex:E76B2413958B00E193
aescrypt 1 test.out test.denc hex:E76B2413958B00E193
cat test.denc
this is a test message

使用 openssl:

openssl enc -in out.test -out outfile.txt -d -aes256 -k E76B2413958B00E193
bad magic number

一些当前不工作的示例节点代码

    var crypto = require('crypto');
    var AESCrypt = {};

AESCrypt.decrypt = function(cryptkey, iv, encryptdata) {
    encryptdata = new Buffer(encryptdata, 'base64').toString('binary');

    var decipher = crypto.createDecipheriv('aes-256-cbc', cryptkey, iv),
        decoded = decipher.update(encryptdata, 'binary', 'utf8');

    decoded += decipher.final('utf8');
    return decoded;
}

AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
    var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv),
         encryptdata = encipher.update(cleardata, 'utf8', 'binary');

    encryptdata += encipher.final('binary');
    encode_encryptdata = new Buffer(encryptdata, 'binary').toString('base64');
    return encode_encryptdata;
}

var cryptkey   = crypto.createHash('sha256').update('Nixnogen').digest(),
    iv         = 'a2xhcgAAAAAAAAAA',
    buf        = "Here is some data for the encrypt", // 32 chars
    enc        = AESCrypt.encrypt(cryptkey, iv, buf);
    var dec        = AESCrypt.decrypt(cryptkey, iv, enc);

console.warn("encrypt length: ", enc.length);
console.warn("encrypt in Base64:", enc);
console.warn("decrypt all: " + dec);

这每次都会导致错误或垃圾文本。我也尝试过调整各种东西。

我已经尝试了一百种不同的方法,包括使用 -pass pass:password arg 无济于事。使用 nodejs,我要么得到严重的解密错误,要么在解密时出现乱码。我尝试过网上很多教程,例如this 一个,以及来自this thread 的建议,以及我能找到的所有其他内容。我读过不同的加密程序使用不同的标准,因此跨平台/程序/语言的兼容性并不总是得到保证,但我想有人曾经处于这种困境并且知道解决方案吗?

我将如何使用 nodejs 解密由 aescrypt2(或类似程序)加密的数据?我只能使用系统 exec 调用并让节点执行 aescrypt2 来解密/加密数据,这并不理想,因为它会大大减慢速度。我愿意使用与 aescrypt2 不同的程序。唯一的要求是它必须在Linux上运行,不能使用openssl库(因为目标系统不支持它们),程序应该小而简单,由于空间限制,最重要的是,加密/解密需要与nodejs兼容。任何帮助将不胜感激。

【问题讨论】:

  • 这个C代码怎么样?
  • 我目前正在尝试使用 mbedlts aescrypt 示例程序:github.com/ARMmbed/mbedtls/blob/development/programs/aes/…,它不适用于任何节点加密库。我正在寻找可以做到的来源,或使其工作的方法。
  • 慢下来,研究一下如何编写代码。
  • 是的,我正在尝试这样做,但是在遵循 mbedtls api 文档时遇到了麻烦,因为 C 不是我最好的语言,所以我正在寻求帮助。我希望有人已经有了解决方案。
  • 恕我直言,这是应该提出问题的方式。措辞得当,清楚地证明了研究工作。我也不认为接近投票适用,这是一个关于如何解决问题的问题,而不是推荐一些图书馆。

标签: c node.js aes


【解决方案1】:

我将如何使用 nodejs 解密由 aescrypt2(或类似程序)加密的数据?

很抱歉,没有比这更好的答案了:做与 aescrypt2 在解密文件时所做的完全相同的事情。您已自行链接到源代码,因此只需在 node.js 中执行与在 C 中的解密分支中相同的步骤即可。

首先,熟悉layout of the file containing the encrypted data

    /*
     *  The encrypted file must be structured as follows:
     *
     *        00 .. 15              Initialization Vector
     *        16 .. 31              AES Encrypted Block #1
     *           ..
     *      N*16 .. (N+1)*16 - 1    AES Encrypted Block #N
     *  (N+1)*16 .. (N+1)*16 + 32   HMAC-SHA-256(ciphertext)
     */

因此,您需要从文件中提取 IV、加密块和 HMAC,而不是尝试使用 openssl 尝试解密整个内容(您的 openssl 示例也没有使用正确的 IV,而是尝试导出它从提供的密钥 - 阅读man page)。

接下来,获取正确的密钥。用于加密/解密的actual key used 不是在命令行中提供的,而是使用 SHA256 使用命令行上传递的密钥对 IV 进行 8192 次散列迭代。

最后,他们使用 AES-256-ECB(您的 openssl 和 node.js 示例使用 CBC!)每 16 个字节解密一次,XOR the result 使用前 16 个字节(IV 用于前 16 个字节) .

可能还有更多,我只是列出了我在阅读 aescrypt2.c 代码时看到的最明显的东西。

所以我的建议是:尝试在 node.js 中编写相同的逻辑,并尝试为相应的 mbedtls 对应项查找 node.js 加密调用。

我不是加密专家,但我敢打赌,aescrypt 实现有很多感觉很复杂的步骤(例如生成实际使用的密钥),因为他们知道如何进行加密并且只是以正确的方式进行。

【讨论】:

  • 谢谢,老实说,我什至不确定 aescrypt2 默认使用的是哪个密码,所以这绝对有帮助。如果有人在接下来的两天内没有提出更简单的解决方案,我可能最终会接受这个答案。我会试试你的建议,明天再报告。再次感谢。
  • 很高兴我能帮上忙。如前所述,aescrypt2 方式似乎不容易的原因很可能是因为它需要以这种方式完成,以确保整个加密过程的安全......
  • 手册说——'实际使用的 IV:这必须表示为仅由十六进制数字组成的字符串。当使用 -K 选项仅指定键时,必须显式定义 IV。当使用其他选项之一指定密码时,IV 是从此密码生成的。 ——这是否意味着我将硬编码一个 IV 用于每条消息,如果它不是从密钥派生的?如果我对每条消息使用不同的 IV,那会破坏预共享密钥的意义,对吗?
  • 这意味着如果您不从密钥中派生它,则应自己生成IV(使其尽可能随机)。你永远不会硬编码一个!此外,它不是预共享密钥。预共享密钥永远不能公开,IV 可以。它只是为了随机性而存在的,所以我认为如果您想将其与某物进行比较,请将其与密码盐进行比较。
猜你喜欢
  • 2020-12-03
  • 2018-11-29
  • 2019-12-28
  • 2020-11-23
  • 2011-01-15
  • 2012-10-07
  • 2021-11-17
  • 2013-01-17
  • 1970-01-01
相关资源
最近更新 更多