javascript - C - tiny-aes-c 和 Javascript CryptoJS 互操作性

标签 javascript c node.js aes cryptojs

使用 tiny-aes-c .考虑以下 C 代码:

int main(int argc, char const *argv[])
{
    uint8_t key[6] = { 's','e','c','r','e','t' };
    uint8_t iv[16]  = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };

    uint8_t in[6]  = { 'm','e','s','a','g','e'};

    uint8_t out[6] = {0x17, 0x8d, 0xc3, 0xa1, 0x56, 0x34};
    struct AES_ctx ctx;

    AES_init_ctx_iv(&ctx, key, iv);
    AES_CTR_xcrypt_buffer(&ctx, in, 6);    

    printf("idx\t encrypted\t expected");
    for(int i=0 ; i<6 ; i++){
        printf("\n[%i]\t %.2x\t\t %.2x" , i , in[i], out[i]);
    }

    return 0;
}

代码加密消息并将结果与​​预期输出进行比较。代码运行正常,输出如下:

idx      encrypted       expected
[0]      17              17
[1]      8d              8d
[2]      c3              c3
[3]      a1              a1
[4]      56              56
[5]      34              34

我有另一个服务,一个使用 CryptoJS 的 NodeJS 服务器.
我的问题是:如何转换 C 结果({0x17, 0x8d, 0xc3, 0xa1, 0x56, 0x34})以便它匹配 CryptoJS 可以处理的内容?


编辑: 详细说明一下。出于本次讨论的目的,C 结果通过网络传输,因此应将其转换为 String。据我所知,CryptoJS 使用 base64 作为其 AES 方法的输入,解密为字节,稍后可以将其转换为纯文本:

var bytes  = CryptoJS.AES.decrypt(BASE_64_STRING, SECRET);
var plaintext = bytes.toString(CryptoJS.enc.Utf8);

使用 CryptoJS 对同一消息 + secret 的加密结果是:U2FsdGVkX1/TAYUIFnXzC76zb+sd8ol+2DfKCkwITfY= ( JS Fiddle ) 并且每次运行都会发生变化。

更新 2:
感谢@MDTech.us_MAN 的回答,我对 JS 和 C 代码都做了一些更改,但我仍然缺少拼图。

C:

int main(int argc, char const *argv[])
{
    uint8_t key[16] = { 's','e','c','r','e','t','s','e','c','r','e','t','1','2','3','4' };
    uint8_t iv[16]  = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
    uint8_t in[7]  = { 'm','e','s','s','a','g','e'};

    struct AES_ctx ctx;

    AES_init_ctx_iv(&ctx, key, iv);
    AES_CTR_xcrypt_buffer(&ctx, in, 7);

    printf("Encrypted: ");
    for(int i=0 ; i<7 ; i++){
        printf("%.2x" , in[i]);
    }

    return 0;
}

加密后的十六进制字符串C输出:cba9d5bc84113c,转换成Base64结果为:y6nVvIQRPA==

在 JS 方面,我明确地使用没有填充的 CTR 模式,并像这样启动(希望)相同的 iv:

const CryptoJS = require("crypto-js");
let iv = CryptoJS.enc.Hex.parse('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'); // 16 Bytes (same as the C code)
let message = CryptoJS.AES.decrypt("y6nVvIQRPA==", "secretsecret1234", { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
console.log(message.toString());

解密结果:a47172dfe151c7 而不是预期结果“message”。

我错过了什么?

最佳答案

您应该更仔细地阅读 CryptoJS 文档。默认情况下,它使用 CBC 模式进行加密,因此您应该更改您的微型 AES 实现以使用它。

CryptoJS supports the following modes:

  • CBC (the default)

另请注意,CryptoJS 默认启用填充,而 tiny-AES 根本没有。因此,消息必须是16的倍数。(或者你可以手动使用自己的padding实现)

No padding is provided so for CBC and ECB all buffers should be mutiples of 16 bytes. For padding PKCS7 is recommendable.

然后,请注意 CryptoJS 通过 key 大小自动选择 AES 变体:

CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key.

因此,您必须在微型 AES 代码中考虑所有这些因素。

关于javascript - C - tiny-aes-c 和 Javascript CryptoJS 互操作性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50274899/

相关文章:

javascript - Ext js 消息框 - 无法在 IE7 中打开

javascript - 使用 mootools Fx 缩放背景大小

c - HTTP 客户端从某些服务器获取 "Connection reset by peer"(TCP RST),但从其他服务器获取不到

在 C 中具有不断增长的堆栈的协程

json - 接收 NPM 错误 : Unexpected string in JSON at position 20938 within an ionic 3 project

javascript - 如何使用 JS 显示 3 的倍数变量?

javascript - 通过 JavaScript 点击 Flash 对象

c - 编译C程序时 undefined symbol

node.js - Passportjs Facebook 策略中电子邮件字段是可选的

Node.js + Webpack + TypeScript : access to path of project with source files (not usage project)