Shl*_*rtz 8 javascript c aes node.js 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;
}
Run Code Online (Sandbox Code Playgroud)
代码对消息进行加密,并将结果与预期输出进行比较.代码工作正常,输出如下:
idx encrypted expected
[0] 17 17
[1] 8d 8d
[2] c3 c3
[3] a1 a1
[4] 56 56
[5] 34 34
Run Code Online (Sandbox Code Playgroud)
我有另一个服务,一个使用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);
Run Code Online (Sandbox Code Playgroud)
与CryptoJS相同的消息+秘密的加密结果是: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;
}
Run Code Online (Sandbox Code Playgroud)
加密的HEX字符串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());
Run Code Online (Sandbox Code Playgroud)
解密的结果:a47172dfe151c7而不是预期的结果"消息".
我错过了什么?
您应该仔细阅读CryptoJS文档.默认情况下,它使用CBC模式进行加密,因此您应该更改您的tiny-AES实现以使用它.
CryptoJS支持以下模式:
- CBC(默认)
另请注意,CryptoJS默认启用填充,而tiny-AES根本没有填充.因此,消息必须是16的倍数.(或者您可以手动使用自己的填充实现)
没有提供填充,因此对于CBC和ECB,所有缓冲区应该是16字节的多个.对于填充PKCS7是值得推荐的.
然后,请注意CryptoJS按键大小自动选择AES变体:
CryptoJS支持AES-128,AES-192和AES-256.它将根据您传入的密钥的大小选择变体.如果使用密码,则它将生成256位密钥.
因此,您必须在微型AES代码中考虑所有这些因素.
感谢@MDTech.us_MAN和这个堆栈溢出问题,我找到了一个解决方案,在修复模式和填充后,不同之处在于我在JS端解析秘密的方式。在以下示例中,秘密被解析为十六进制字符串:
const CryptoJS = require("crypto-js");
let iv = CryptoJS.enc.Hex.parse('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'); // 16 Bytes
let secret = CryptoJS.enc.Hex.parse('73656372657473656372657431323334'); // 16 Bytes == "secretsecret1234"
let message = CryptoJS.AES.decrypt("y6nVvIQRPA==", secret, { iv: iv, mode: CryptoJS.mode.CTR, padding: CryptoJS.pad.NoPadding });
console.log(message.toString(CryptoJS.enc.Utf8)); // -> message
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
459 次 |
| 最近记录: |