同样一份 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 库……

2336 次点击
所在节点    C
38 条回复
skydiver
2016-01-25 11:18:56 +08:00
为啥是 unsigned char 不应该是转换成 void *么,再不济也是 unsigned char*
zonyitoo
2016-01-25 11:25:27 +08:00
memcpy(key,(unsigned char)"test",32);

看到这句笑翻了………
除了上面说的越界之后,我还有个问题,为什么要强转类型为 unsigned char ?
402124773
2016-01-25 11:47:27 +08:00
你把这个程序在同一个平台下连续运行两次,看看结果是否一致,不就可以得出“是否是因为 memcpy 长度太长导致后面的数据有问题”的结论了吗???
auser
2016-01-25 12:39:41 +08:00
楼上说的几处代码都是不好的,楼主还是改过来好了。

以前用 C 实现过一整套的 aes_cbc.
里边除了 block cipher modes 需要了解, padding 也要关注的。还有初始化向量 IV 这些细节。

建议楼主搞清楚这些概念后选择个合适的库好了,不要直接从这些底层入手。
hitmanx
2016-01-25 12:44:42 +08:00
没看明白.memset 和 memcpy 没关系,可以 memset 去清空 32 位为'\0',但是依然只去 memcpy 前几位,这样后面几位并不会受影响."test"作为 const char*,应该是存在全局变量的 read-only 段的,memcpy(,,32)会把这个段后面的数据一起去拷贝,结果是未定义的.另外这儿感觉用 strncpy 会比 memcpy 好一些.
wadahana
2016-01-25 12:49:53 +08:00
@402124773 有可能是一样的, 表忘了可能会有 “烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫”
k9982874
2016-01-25 12:50:28 +08:00
"不同语言的库加密出来的结果都不一样,也不能互相解密"

只能说你的实现有问题,算法正确的话出来的值是可以用任何语言的实现解密的。

"memcpy(key,(unsigned char)"test",32);"
如果算法实现没问题,这句应该是罪魁祸首,原因前面的同学已经说了。

最近刚实现了一套 C 的 AES ,产生的结果 PHP JAVA 都可以互解。
jasontse
2016-01-25 13:00:26 +08:00
看标题就知道是未定义内存的坑
wohenyingyu01
2016-01-25 13:01:14 +08:00
@402124773 运行过是一样的额
wohenyingyu01
2016-01-25 13:03:34 +08:00
@k9982874 这个代码奇怪的地方在于,无论加密出来的结果有多不一样,只要在同一个环境下对结果去解密都能解出正确的来,如果把结果从外面传进来,就解不出……
wizardoz
2016-01-25 13:03:36 +08:00
@wohenyingyu01 不仅仅是 32 字节和 5 字节的问题。你把指针强制转换成 unsigned char 了,少个星号!
也就是说指针的值溢出后变成了一个 0-255 之间的值。
wizardoz
2016-01-25 13:06:37 +08:00
@wizardoz 难道是语言特性?抱歉我以为是 C 语言,请忽略我。
wohenyingyu01
2016-01-25 13:07:59 +08:00
@wizardoz 火眼金睛!不过我看了下代码里面是有的,不知道为啥复制过来没了
wohenyingyu01
2016-01-25 13:09:22 +08:00
@skydiver 我看了下代码里面是有的,不知道为啥复制过来没了额
waruqi
2016-01-25 13:51:14 +08:00
这代码 也是醉了。。
sophymax
2016-01-25 14:13:11 +08:00
其实是还没完全理清那个加密算法 , 有些参数需要设置的 , 某个库默认设置的不一样 , salt 值 IV 值 之类的 , 还有可能是最后是不是多了一个字节的内存
skydiver
2016-01-25 14:58:30 +08:00
@wohenyingyu01 原来是变成 markdown 粗体了……
wohenyingyu01
2016-01-25 16:58:59 +08:00
@sophymax 那个 c 代码完全看不懂,理不清了,可能还需要从 aes 原理入手研究了,实在不行换一个方法,谢啦

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

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

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

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

© 2021 V2EX