用 tinyAES 加密跨平台运行结果不同

2020-03-17 20:51:08 +08:00
 dtsdao
代码: https://paste.ubuntu.com/p/nGBZxQ4sbY
引用的 AES 库: https://github.com/kokke/tiny-AES-c
引用的 MD5 库: https://bobobobo.wordpress.com/2010/10/17/md5-c-implementation/

大概的意思就是用 AES 加密然后获取 MD5

在 MinGW/Linux 编译运行后相同的输入结果总是有差别,问题究竟出在哪呢?

或者,该怎样用其他语言改写这段代码?
2605 次点击
所在节点    程序员
21 条回复
lcdtyph
2020-03-17 20:59:32 +08:00
因为加密完 text 存储的已经不是字符串了啊,没有\0 做结尾了。所以 digestString 很有可能读到不属于 text 的值。你要用的是
md5.digestMemory((char *)text, sizeof text);
dtsdao
2020-03-17 21:12:45 +08:00
@lcdtyph text 数组我自认为已经开的挺大了,之前开小了连 windows 结果都不正确
说实话,我觉得用 C++写这个真的头疼,这段是反编译出来的所以看着特别难受,用其它语言改写总是结果不对
lcdtyph
2020-03-17 21:24:42 +08:00
@dtsdao #2 结果都不正确原因是 digestString 不知道读到哪里才停止啊,如果你加密之后的数据里没有'\0'或者'\0'在中间就出现了你的 md5 结果肯定不对啊,这和你 text 数组开多大有什么关系呢?
BrettD
2020-03-17 21:29:05 +08:00
是不是逻辑写错了
dtsdao
2020-03-17 21:34:58 +08:00
@lcdtyph 我试了一下用 digestMemory,运行结果还是不一样。

Line 27: puts(md5.digestMemory(text, sizeof text));

input:test1234

Linux:a54e0cfdb3158654122d193cdf29c6e5
Windows:fb4c2c022c39db620d88476666f5f79a
dtsdao
2020-03-17 21:36:19 +08:00
@BrettD 逻辑不是我写的,是反编译的。Windows 跑得很好,Linux 就不行了。源程序是用的 NDK 生成的 arm 的 so,我手里没有源码。
sfqtsh
2020-03-17 21:44:19 +08:00
1 换行符\r\n
2 getchar 的返回类型是 int
lcdtyph
2020-03-17 21:49:54 +08:00
@dtsdao #5
我编译一下试试看
还有一个问题是你这么短的输入,那个 aes_ecb_encrypt 根本就没机会运行
dtsdao
2020-03-17 21:57:30 +08:00
@sfqtsh 1.都是在 bash 环境运行,换行符统一\n 2.强制转换就转换吧,我快读多少年来都这么写的
dtsdao
2020-03-17 22:27:37 +08:00
...重新反编译了一下发现贴的代码变量类型不太对,详见下图吧

https://i.loli.net/2020/03/17/OJY7bdoK9xwnjB2.png
springz
2020-03-17 22:35:34 +08:00
问问题好歹给一个最小可复现,再说反编译,额。总是想到不好的事情。
dtsdao
2020-03-17 22:42:33 +08:00
@springz 已经给了复现方案,所有源码都能获取到。这是已弃用的内部软件的源码,不要想多。
lcdtyph
2020-03-17 22:50:51 +08:00
@dtsdao #12
我吐了,md5.h 里面有一行 typedef unsigned long int UINT4;
这导致 UINT4 在 64 位 unix 机器上根本不是 4byte,而是 8byte。而 win 上 long 总是 4byte 的所以 win 上的结果是对的。
lcdtyph
2020-03-17 23:01:38 +08:00
你可以把那行改成
#include <stdint.h>
typedef uint32_t UINT4;
dtsdao
2020-03-17 23:11:57 +08:00
@lcdtyph 草,我就猜是这样,我还以为是 uint_8 的事呢,结果查了半天 tinyaes 相关问题都没查出来,感谢您帮忙定位,这个库太坑了。顺便求下用其他库改写的源码,这个真的看着太丑了。

问题相关: https://stackoverflow.com/questions/697361/md5-hash-calculates-differently-on-server
lcdtyph
2020-03-17 23:23:54 +08:00
@dtsdao #15
我比较熟悉 openssl……
不过如果你运行在嵌入式设备的话可以用 mbedtls
我写个 demo
dtsdao
2020-03-17 23:30:29 +08:00
话说写这个玩意的人貌似根本就没管 AES 的 Padding 之类的吧,我觉得它能运行都很神奇,要不是登录校验需要的话打死不会用 C 复现的...
lcdtyph
2020-03-18 00:07:35 +08:00
@dtsdao #15
```
#include <stdio.h>

#include <mbedtls/md.h>
#include <mbedtls/cipher.h>

uint8_t text[80] = {'t', 'e', 's', 't', '1', '2', '3', '4'};

int main()
{
uint8_t buf[16] = {0};

mbedtls_md_context_t md5;
mbedtls_md_init_ctx(&md5, mbedtls_md_info_from_type(MBEDTLS_MD_MD5));

mbedtls_md_starts(&md5);

mbedtls_md_update(&md5, text, sizeof text);

mbedtls_md_finish(&md5, buf);

for (int i = 0; i < sizeof buf; ++i) {
printf("%02hhx", buf[i]);
}
printf("\n");

return 0;
}
```
dtsdao
2020-03-18 00:13:16 +08:00
@lcdtyph 我说的倒不是 MD5,主要是前面那块 AES,直接用 AES_ECB_encrypt 就对,加了 padding 就错,如果能用 openssl 改写就好了
lcdtyph
2020-03-18 00:49:19 +08:00
@dtsdao #19
ECB 模式无所谓 padding,因为他默认输入是 16byte 的整数倍,就是要求自己 padding。在你的代码里其实就相当于 zero padding

```
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#include <mbedtls/md.h>
#include <mbedtls/cipher.h>

uint8_t key[] = "88a2a91ee2126bfd";
uint8_t text[80] = {'t', 'e', 's', 't', '1', '2', '3', '4'};
uint8_t len = 0;

int main()
{
mbedtls_cipher_context_t ctx;

mbedtls_cipher_init(&ctx);
mbedtls_cipher_setup(&ctx, mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB));

mbedtls_cipher_setkey(&ctx, key, 128, MBEDTLS_ENCRYPT);
mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_ZEROS);

uint8_t buf[80];
size_t olen = sizeof buf;
size_t idx = 0;
mbedtls_cipher_update(&ctx, text, 16, buf + idx, &olen);
idx += olen;
olen = (sizeof buf) - idx;
mbedtls_cipher_finish(&ctx, buf + idx, &olen);
idx += olen;

mbedtls_cipher_free(&ctx);

for (int i = 0; i < idx; ++i) {
printf("%02hhx", buf[i]);
}
printf("\n");

return 0;
}
```

ECB 模式其实也不需要上面的 mbedtls_cipher_finish,但是为了过程完整我还是写出来了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/653678

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX