AES-256-CBC-PKCS5Padding用c语言实现,并支持Android手机的调用

来源:互联网 发布:维旺迪收购育碧 知乎 编辑:程序博客网 时间:2024/05/21 17:54

转载:http://www.longdw.com/aes-256-cbc-c-android-pkcs5padding/?utm_source=tuicool&utm_medium=referral

参考:http://www.longdw.com/aes-256-cbc-c-android-pkcs5padding/

首先声明一下,以下所写的并不是深入研究AES算法,而是本人结合网络上高人写的文章,朋友的帮忙总结出了一套自认为更安全的支持Android的加密方式(不是原生的)。

公司给的需求是将密码和请求的URL地址采用AES加密,在网上找到了一位高人写的Object-c、C#、Java、Android都通用的版本,这里给上链接地址,通用AES加密版本sample_java_aes256_imcore_net.zip,已经上传CSDN或者百度云),同时也直接附上附件,点击这里下载通用版本,在这里向原作者表示敬意!

可能大家都觉得奇怪,有现成的不用非要自己折腾用C语言来实现?这里我就要说下我的想法了,大家都知道Android中可以直接调用封装好的方法进行加密,但是这有个弊端,就是使用的密钥必须存储在Java代码中,大家都知道Java代码的安全性并不好,哪怕你打包混淆过别人都有办法看到里面的代码。后来我就放弃了把密钥(以下简称key)放在Java代码中的想法了。这个问题向我的好友@leepood也请教过,他给了我一些思路,然后我总结出了两套方案:1、key存储在c中,然后打包成so文件给Android调用;2、key存储在c中,Android端传递明文给c,然后通过c来加密并返回密文。后来决定使用第二种方案!这里要感谢下我的好友leepood。

然后就是接下来近4天的折腾了。参考了网上各种代码,c语言早忘光了(其实就是上学的时候没学好),看到什么char[],char* 脑袋立马就大了,但是没办法,还得硬着头皮去看。前前后后我算了下,至少尝试了网上提供的5套代码,没有一个是符合要求的,也就是快放弃的时候看到了pudn网站上提供的这套代码(pudn-AES.zip,已经上传CSDN或者百度云),没有积分的可以点击pudn-AES下载,这套代码注释很详细,以为看到希望了我经过一天多时间的测试发现不是代码的问题,而是这套代码完全不符合我的要求。下面我附上代码:


为了能稍微看懂些这套代码,至少是为了能修改代码适应我的需求吧,无意中搜索到了这篇文章,这里是文章的地址,感兴趣的也可以下载,我这里也提供下载地址,点击AES加密介绍AES加密介绍.pdf已经上传CSDN或者百度云。由于目前C#端和IOS端采用的都是AES256并且是PKCS5Padding填充的方式,上面默认提供的是AES128方式的加密


根据上面的说明,修改代码Nk=8, Nr=14。然后测试代码,并对比Java原生的加密方式返回的字节流,一样的!!!Oh my god!皇天不负有心人啊!但高兴的还是太早了,输入的数据是16字节的还好,超过或不足16字节就是个坑啊!然后又看到上面pdf文章中写的这么一句话:


尼玛,这可怎么办!又是各种baidu,google,然后就看到了这篇本以为又遇到救星的文章,这里是文章地址。按文章中的说明:如果不足16字节的话我填充了0×06,我擦,还真可以。然后就是巨坑了,文章中说如果是16的倍数就填充0X16,而且也没说明如果大于16而不是16的倍数的情况。我就按他说的填充0X16!!!!怎么测试都跟Android端的字节流对不上。后来又换了几套代码还是不行!只能加密一组,后面填充16字节的数据怎么加密的都对不上。这套代码就这样废弃了,感兴趣的可以试下,代码应该是没问题的,后来发现(也就是我接下来要说的)填充的并不是0X16,而是0×10(十进制16),作者坑人不带商量的。后来找了一堆资料,有人说可以直接使用openssl中提供的AES加密方法,但是openssl这个开源c库太大了,我想单独把AES加密部分抠出来不太现实,关联的文件太多了,而且就一个小小的AES加密没必要用这么大的库。

又有放弃的念头了,然后就无所事事,萎靡不振,头昏脑胀的加了一个openssl的qq群,没抱任何希望的在里面发了条求助信息,过了一会一位好心的大哥回复了我,然后一番胡侃之后,在今天早上他给了我他写的代码。在这里真要感谢下这位大哥了!研究了下他的代码,然后他也指导了一番,终于在今天大功告成了!

大神提供的代码在这里下载aes256_test.rar已经上传CSDN或者百度云)。这套原生的支持输入3组(每组16个字节)明文数据就输出三组加密后的数据。而且没有填充功能,需要自己手动填充。说到填充这里需要补充几点知识,也是从网上看到的。如下:

算法/模式/填充                        16字节加密后数据长度         不满16字节加密后长度
AES/CBC/NoPadding                               16                                       不支持
AES/CBC/PKCS5Padding                        32                                          16
AES/CBC/ISO10126Padding                  32                                           16
AES/CFB/NoPadding                               16                                  原始数据长度
AES/CFB/PKCS5Padding                        32                                           16
AES/CFB/ISO10126Padding                  32                                            16
AES/ECB/NoPadding                               16                                         不支持
AES/ECB/PKCS5Padding                        32                                            16
AES/ECB/ISO10126Padding                   32                                           16
AES/OFB/NoPadding                               16                                   原始数据长度
AES/OFB/PKCS5Padding                        32                                            16
AES/OFB/ISO10126Padding                  32                                             16
AES/PCBC/NoPadding                             16                                        不支持
AES/PCBC/PKCS5Padding                      32                                             16
AES/PCBC/ISO10126Padding                32                                             16

可以看到,在原始数据长度为16的整数倍时,假如原始数据长度等于16*n,则使用NoPadding时加密后数据长度等于16*n,其它情况下加密数据长度等于16*(n+1)。在不足16的整数倍的情况下,假如原始数据长度等于16*n+m[其中m小于16],除了NoPadding填充之外的任何方式,加密数据长度都等于16*(n+1);NoPadding填充情况下,CBC、ECB和PCBC三种模式是不支持的,CFB、OFB两种模式下则加密数据长度等于原始数据长度。

说到填充在这里也要说明下,不能被网络上复制来复制去的文章忽悠了。

1、如果输入的数据不足16个字节,需要补齐(填充)到16个字节,比如:10个字节就补齐6个6,11个字节就补齐5个5,以此类推;
2、如果输入的数据是16的整数倍个字节,需要在数据后面填充16个0×10(也可以是10进制的16);
3、如果输入的数据大于16且不是16的倍数,你需要把字符串补齐到16位,比如:如果少4位,就补充4个4, 如果少5位就补充5个5,少n位,补充n个n。

结合大神提供的代码和他的指点,然后修改了他的源码,自己写了一套适合在Android端使用的加密方式,可以输入任何长度的数据都可以返回。

源码下载。jni_temp1.zip已经上传CSDN或者百度云




0 0
原创粉丝点击