主要在做 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 库……
1
zhicheng 2016-01-24 23:35:48 +08:00 1
memcpy(key,(unsigned char)"test",32);
这行 memcpy 很是酸爽。 |
2
w2exzz 2016-01-24 23:38:16 +08:00 via Android
1 楼说得对……这里出现了随机数据
|
3
am241 2016-01-24 23:38:49 +08:00
这算是下标越界吧
|
4
ilotuo 2016-01-24 23:38:56 +08:00 via Android 1
内存操作错误 导致变量或者函数指针乱了
我也遇过类似的 |
5
codecrash 2016-01-25 00:17:23 +08:00 via Android
我遇到过同样一份代码 vc 和 gcc 编译都能通过,但是 vc 的会崩溃,一直不明原因。后来调试发现, vc 编译的东西对象的析构顺序和 gcc 不一样,这导致了空指针的出现,所以就无法正常运行了。
|
6
catlove 2016-01-25 09:19:20 +08:00
看到这行我就醉了。。。。
|
7
catlove 2016-01-25 09:20:15 +08:00 1
memcpy(key,(unsigned char)"test",32);
看到这行我就醉了。。。。 |
8
jukka 2016-01-25 09:46:00 +08:00
man memcpy 了之后再来写代码。
|
9
kobe1941 2016-01-25 09:47:50 +08:00 1
@catlove
函数原型: void *memcpy(void *dest, const void *src, size_t n); 功能: 从源 src 所指的内存地址的起始位置开始拷贝 n 个字节到目标 dest 所指的内存地址的起始位置中 楼主的操作每次都从随机地址开始拷贝。 |
10
wohenyingyu01 OP |
11
wohenyingyu01 OP @wohenyingyu01 而且每次同一环境运行的结果也是固定的……
|
12
wohenyingyu01 OP @wohenyingyu01 打错了,上面给的
|
13
wohenyingyu01 OP |
14
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); |
15
wohenyingyu01 OP @xujif 但是 aes 要求传入的必需是 32 个字节的,所以它用了 memset(buf,0,32);去初始化 32 字节内存,只要存进去的是 32 字节以下的,多出来的位数都会用'\0'补全,这个理论我也用调试印证了,多出来的部分确实是\0 补全的
|
16
tghgffdgd 2016-01-25 10:45:48 +08:00
@wohenyingyu01 "test"补全的\0 只能保证一位,你复制 32 个进去, 5 个之后已经不一定是\0 了,谁告诉多出来的部分确实是\0 补全的。
|
17
xujif 2016-01-25 10:46:27 +08:00
@wohenyingyu01 memcpy 会强制拷贝 32 个字节,在这里前面 memset 是多余的,调试模式很多编译器会对变量填 0,release 并不会。
|
18
wohenyingyu01 OP |
19
Echoldman 2016-01-25 10:55:18 +08:00
memcpy 的 size 是字节,楼主你的调用,是按照位来算的
|
20
viikker 2016-01-25 10:55:28 +08:00 via Android
cbc 不是要初始化 iv 么? iv 是怎么来的
|
21
skydiver 2016-01-25 11:18:56 +08:00 via Android
为啥是 unsigned char 不应该是转换成 void *么,再不济也是 unsigned char*
|
22
zonyitoo 2016-01-25 11:25:27 +08:00
memcpy(key,(unsigned char)"test",32);
看到这句笑翻了……… 除了上面说的越界之后,我还有个问题,为什么要强转类型为 unsigned char ? |
23
402124773 2016-01-25 11:47:27 +08:00
你把这个程序在同一个平台下连续运行两次,看看结果是否一致,不就可以得出“是否是因为 memcpy 长度太长导致后面的数据有问题”的结论了吗???
|
24
auser 2016-01-25 12:39:41 +08:00 via Android
楼上说的几处代码都是不好的,楼主还是改过来好了。
以前用 C 实现过一整套的 aes_cbc. 里边除了 block cipher modes 需要了解, padding 也要关注的。还有初始化向量 IV 这些细节。 建议楼主搞清楚这些概念后选择个合适的库好了,不要直接从这些底层入手。 |
25
hitmanx 2016-01-25 12:44:42 +08:00 1
没看明白.memset 和 memcpy 没关系,可以 memset 去清空 32 位为'\0',但是依然只去 memcpy 前几位,这样后面几位并不会受影响."test"作为 const char*,应该是存在全局变量的 read-only 段的,memcpy(,,32)会把这个段后面的数据一起去拷贝,结果是未定义的.另外这儿感觉用 strncpy 会比 memcpy 好一些.
|
27
k9982874 2016-01-25 12:50:28 +08:00
"不同语言的库加密出来的结果都不一样,也不能互相解密"
只能说你的实现有问题,算法正确的话出来的值是可以用任何语言的实现解密的。 "memcpy(key,(unsigned char)"test",32);" 如果算法实现没问题,这句应该是罪魁祸首,原因前面的同学已经说了。 最近刚实现了一套 C 的 AES ,产生的结果 PHP JAVA 都可以互解。 |
28
jasontse 2016-01-25 13:00:26 +08:00 via iPad
看标题就知道是未定义内存的坑
|
29
wohenyingyu01 OP @402124773 运行过是一样的额
|
30
wohenyingyu01 OP @k9982874 这个代码奇怪的地方在于,无论加密出来的结果有多不一样,只要在同一个环境下对结果去解密都能解出正确的来,如果把结果从外面传进来,就解不出……
|
31
wizardoz 2016-01-25 13:03:36 +08:00
@wohenyingyu01 不仅仅是 32 字节和 5 字节的问题。你把指针强制转换成 unsigned char 了,少个星号!
也就是说指针的值溢出后变成了一个 0-255 之间的值。 |
33
wohenyingyu01 OP @wizardoz 火眼金睛!不过我看了下代码里面是有的,不知道为啥复制过来没了
|
34
wohenyingyu01 OP @skydiver 我看了下代码里面是有的,不知道为啥复制过来没了额
|
35
waruqi 2016-01-25 13:51:14 +08:00
这代码 也是醉了。。
|
36
sophymax 2016-01-25 14:13:11 +08:00
其实是还没完全理清那个加密算法 , 有些参数需要设置的 , 某个库默认设置的不一样 , salt 值 IV 值 之类的 , 还有可能是最后是不是多了一个字节的内存
|
37
skydiver 2016-01-25 14:58:30 +08:00
@wohenyingyu01 原来是变成 markdown 粗体了……
|
38
wohenyingyu01 OP @sophymax 那个 c 代码完全看不懂,理不清了,可能还需要从 aes 原理入手研究了,实在不行换一个方法,谢啦
|