同样一份 c 代码,用 oc 调用的结果和直接 gcc 编译运行的结果不一样是为什么

2016-01-24 23:13:31 +08:00
 wohenyingyu01

主要在做 aes 加密这块,因为涉及到服务器,安卓和 iOS 的多平台,试过很多的库,同样的 aes - 256-cbc 算法,不同语言的库加密出来的结果都不一样,也不能互相解密,故想用同一个 c 语言库跨平台运行。 main 函数如下:

int m, n, i, j;
char c;
aes_context ctx;
unsigned char buf[32];
unsigned char key[32];

n=2;
memset(key,0,32);

memcpy(key,(unsigned char)"test",32);
memset(buf,0,32);
memcpy(buf,(unsigned char
)"13911112222+1234567890+313787",32);
aes_set_key( &ctx, key, 128 + n*64);
aes_encrypt( &ctx, buf, buf );
printf("The encrypted data is:\n");
for(i=0;i<32;i++)
{
printf("%02x",buf[i]);
}
printf("\n");
printf("\n");

aes_set_key( &ctx, key, 128 + n * 64 );
aes_decrypt( &ctx, buf, buf );
printf("The decrypted data is:\n");

printf("%s",buf);
printf("\n");
return( 0 );

问题来了,当我在 gcc 下运行此 main 函数的结果是
The encrypted data is:
bd704722da9e2e97de83a43ab442fb693536373839302b333133373837303000

The decrypted data is:
13911112222+1234567890+31378700

当我将 main 函数改为普通函数,在 xcode 用 swift 调用 oc 去调用这个函数,在不传递任何参数进去的情况下,结果为:

The encrypted data is:
562591cb7184ec79998f411268d751423536373839302b333133373837000000

The decrypted data is:
13911112222+1234567890+313787

同样的代码,没有任何改变,为何会运行出两种结果?而且解密只能在同一个函数下解密成功,出了这个函数这个密闻就再也无法解密了,是库有问题吗?求推荐跨平台 aes 库……

2388 次点击
所在节点    C
38 条回复
zhicheng
2016-01-24 23:35:48 +08:00
memcpy(key,(unsigned char)"test",32);

这行 memcpy 很是酸爽。
w2exzz
2016-01-24 23:38:16 +08:00
1 楼说得对……这里出现了随机数据
am241
2016-01-24 23:38:49 +08:00
这算是下标越界吧
ilotuo
2016-01-24 23:38:56 +08:00
内存操作错误 导致变量或者函数指针乱了
我也遇过类似的
codecrash
2016-01-25 00:17:23 +08:00
我遇到过同样一份代码 vc 和 gcc 编译都能通过,但是 vc 的会崩溃,一直不明原因。后来调试发现, vc 编译的东西对象的析构顺序和 gcc 不一样,这导致了空指针的出现,所以就无法正常运行了。
catlove
2016-01-25 09:19:20 +08:00
看到这行我就醉了。。。。
catlove
2016-01-25 09:20:15 +08:00
memcpy(key,(unsigned char)"test",32);
看到这行我就醉了。。。。
jukka
2016-01-25 09:46:00 +08:00
man memcpy 了之后再来写代码。
kobe1941
2016-01-25 09:47:50 +08:00
@catlove
函数原型:
void *memcpy(void *dest, const void *src, size_t n);

功能:
从源 src 所指的内存地址的起始位置开始拷贝 n 个字节到目标 dest 所指的内存地址的起始位置中

楼主的操作每次都从随机地址开始拷贝。
wohenyingyu01
2016-01-25 10:18:28 +08:00
@zhicheng
@kobe1941
@catlove

我知道越界了,但是我用 xcode 调试工具仔细看过了,每次运行到这里的时候超过 test 的部分会自动用\0 补全,就没动它,因为是上门给的使用例子……
wohenyingyu01
2016-01-25 10:18:59 +08:00
@wohenyingyu01 而且每次同一环境运行的结果也是固定的……
wohenyingyu01
2016-01-25 10:20:25 +08:00
@wohenyingyu01 打错了,上面给的
wohenyingyu01
2016-01-25 10:29:44 +08:00
@kobe1941
@zhicheng
@jukka
我又看了一遍发现明明是 memset(buf,0,32); 初始化过一遍了,怎么会出现随机数字,我虽然不会 c 但是不要框我啊😰
xujif
2016-01-25 10:33:54 +08:00
@wohenyingyu01
楼上都告诉你了, memcpy(key,(unsigned char)"test",32); 这个会复制 32 个字节,但是 test 只有 5 个字节
所以你这里应该 memcpy(key,(unsigned char)"test", strlen("test"));或者 memcpy(key,(unsigned char)"test", strlen("test")+1);
wohenyingyu01
2016-01-25 10:41:45 +08:00
@xujif 但是 aes 要求传入的必需是 32 个字节的,所以它用了 memset(buf,0,32);去初始化 32 字节内存,只要存进去的是 32 字节以下的,多出来的位数都会用'\0'补全,这个理论我也用调试印证了,多出来的部分确实是\0 补全的
tghgffdgd
2016-01-25 10:45:48 +08:00
@wohenyingyu01 "test"补全的\0 只能保证一位,你复制 32 个进去, 5 个之后已经不一定是\0 了,谁告诉多出来的部分确实是\0 补全的。
xujif
2016-01-25 10:46:27 +08:00
@wohenyingyu01 memcpy 会强制拷贝 32 个字节,在这里前面 memset 是多余的,调试模式很多编译器会对变量填 0,release 并不会。
wohenyingyu01
2016-01-25 10:49:39 +08:00
@tghgffdgd
@xujif
额,有道理,可能是这个造成的
Echoldman
2016-01-25 10:55:18 +08:00
memcpy 的 size 是字节,楼主你的调用,是按照位来算的
viikker
2016-01-25 10:55:28 +08:00
cbc 不是要初始化 iv 么? iv 是怎么来的

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

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

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

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

© 2021 V2EX