我试图了解如何使用这个c库(tiny-AES-c)。作为一名 Web 开发人员,我正在寻找 this JS fiddle 的等效 C 代码。
JS代码很简单:
// Encrypt
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123');
console.log("Encrypted: " + ciphertext.toString());
// Decrypt
var bytes = CryptoJS.AES.decrypt(ciphertext.toString(), 'secret key 123');
var plaintext = bytes.toString(CryptoJS.enc.Utf8);
console.log("Decrypted: " + plaintext);
给定要加密的消息和秘密,代码会生成加密数据并将结果转换为字符串。
我的C代码:
int main()
{
uint8_t in[] = "my message";
uint8_t key[] = "secret key 123";
struct AES_ctx ctx;
AES_init_ctx(&ctx, key);
printf("ORIG: %s",(char*) in);
// Encrypt
AES_ECB_encrypt(&ctx, in);
printf("\nENC: %s",(char*) in);
// Decrypt
AES_ECB_decrypt(&ctx, in);
printf("\nDEC: %s",(char*) in);
return 0;
}
输出:
ORIG: my message
ENC: ̤�+��5<n]EYK�ظ/����
DEC: my message%
我知道我不应该尝试将结果打印为字符串,但无法弄清楚如何使用 tiny-AES-c API 以及当我尝试使用时获得类似的(与 JS)结果更长的消息我得到了奇怪的结果,让我认为我使用这个库的方式是错误的。
问:与上述 JS 等价的 C 代码是什么?
我是您引用的 AES 库的原作者。
当使用ECB和CBC操作模式时,您需要确保您的密钥、iv和输入/输出块都是16字节长。您还需要决定要使用哪种填充方案。
您可以使用 CTR 模式来避免填充并不再担心块大小。这通常使得 AES 算法更容易使用,因为需要处理的边缘情况更少。
顺便说一句,这在项目自述文件中也有说明:
未提供填充,因此对于 CBC 和 ECB,所有缓冲区都应为 16 字节的倍数。对于填充,建议使用 PKCS7。
ECB 模式对于大多数用途来说被认为是不安全的,并且不在流模式下实现。如果您需要此模式,请为需要加密的每个 16 字节块调用该函数。有关更多详细信息,请参阅维基百科有关欧洲央行的文章。
编辑:
如果您扩展数组,使其长度为 16 个字节并用零填充它们(或者将它们声明为静态,以便它们自动零初始化),我认为它应该适合您:)
正如 @Morten Jensen 建议的那样,您可以使用 CTR 模式 IE:
AES_CTR_xcrypt_buffer
int main()
{
uint8_t key[] = "secret key 123";
uint8_t in[] = "my message";
uint8_t iv[16] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
printf("Length: %lu",strlen((char*)in));
struct AES_ctx ctx;
AES_init_ctx_iv(&ctx, key, iv);
AES_CTR_xcrypt_buffer(&ctx, in, strlen((char*)in));
printf("\nENC: %s",(char*) in); // don't use this string as an input
AES_init_ctx_iv(&ctx, key, iv);
AES_CTR_xcrypt_buffer(&ctx, in, strlen((char*)in));
printf("\nDEC: %s",(char*) in);
return 0;
}
记住,打印加密数据是错误的,如果你想匹配你的JS示例,你应该检查输出并将其转换为base64。
uint8_t in[16] = "my message";
您的缓冲区需要是 16 的倍数。
非常感谢您在帖子中的回答,这已经非常有帮助了!我是一名仍在学习 C 的网络安全学生,所以我为发布一个可能愚蠢的问题的答案而道歉:
我正在开发一个 micro:bit 项目,并尝试使用tinyAES ECB 模式通过无线电将加密消息发送到另一个 micro:bit。我确信我的缓冲区和密钥的大小正确,并且其余的实现都是正确的。但是,接收 microbit 不会解密收到的密文(加密和解密函数分别在单独的设备中调用,所有相关库和所需的代码都已就位)。我一直错误地打印密文来检查/排除故障,并且输出看起来与原始问题中的类似。
根据上面的讨论,我说的对吗?我们需要以 Base64 发送密文,这可能是一个可靠的潜在解决方案?