嘎里三分熟
  • 首页
  • JMusic
  • TSBay
  • 常用工具
  • About Me
  • 留言板
一行代码一世浮生
  1. 首页
  2. Bug集中营
  3. 正文

Java异常之:AES加密兼容Linux

2017年07月14日 4300点热度 5人点赞 1条评论

一、描述

之前有一篇文章中介绍过 AES 的双向加密的实现,此为链接,然后某一天就出异常了。

问题很蛋疼,Windows 系统上开发的项目,利用 AES 双向加密技术,在 Java 代码内对手机号进行加密解密操作。

一切正常,但是项目移到 Linux 系统上,解密就出如下异常:

javax.crypto.BadPaddingException: Given final block not properly padded
       at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
       at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
       at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
       at javax.crypto.Cipher.doFinal(DashoA13*..)
       at chb.test.crypto.AESUtil.crypt(AESUtil.java:386)
       at chb.test.crypto.AESUtil.AesDecrypt(AESUtil.java:254)
       at chb.test.crypto.AESUtil.main(AESUtil.java:40)

定位很精准,就是我的 AESUtil 这个工具类里面的如下代码有问题:

//1.构造密钥生成器,指定为AES算法,不区分大小写
KeyGenerator keygen= KeyGenerator.getInstance("AES");
//2.根据ecnodeRules规则初始化密钥生成器
//生成一个128位的随机源,根据传入的字节数组
keygen.init(128, new SecureRandom(encodeRules.getBytes()));

上面生成 key 的时候出问题了。

二、解决

那就将随机源手动指定就好,即手动生成一个key,

如下为代码改造,完美解决。

//1.构造密钥生成器,指定为AES算法,不区分大小写
KeyGenerator keygen= KeyGenerator.getInstance("AES");
//2.根据ecnodeRules规则初始化密钥生成器
//防止linux下 随机生成key
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(encodeRules.getBytes());
keygen.init(128, secureRandom);

三、原理

其实原理也很蛋疼,网上解决办法大同小异,理由也都是千篇一律:

SecureRandom 实现完全随操作系统本身的內部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;
该实现在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系统上则不同。

简单理解就是在 new SecureRandom() 的时候,两种操作系统上生成的随机数不相同罢了,why,追了下源码。

其实默认情况下,我们需要的 prng(random number algorithm),

在 Windows 环境下,默认是:SHA1PRNG,而 Linux 环境下,则默认是:NativePRNG。

bugCollection-AES.png

再换句话说,Linux 默认使用 NativePRNG, 则它会去本地寻找熵(/ dev /urandom),产生的随机数(直接影响我们加密解密时需要的key)每次都是不一样的,故解密必然会失败了。

所以最直接的方式就是直接指定 prng,使用SHA1PRNG,即用下述方法来建立 SecureRandom,

SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(encodeRules.getBytes());

源码地址:MyGitHub

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: AES bug Linux 加密/解密
最后更新:2017年07月14日

GoldenJet

爱折腾技术的90后漫威小死忠程序员一枚

点赞
< 上一篇
下一篇 >

文章评论

取消回复

通过电子邮件订阅博客

分类目录
  • BootStrap (2)
  • Bug集中营 (6)
  • Java web (3)
  • JavaScript (7)
  • Java基础 (17)
  • Java工具 (5)
  • Linux (3)
  • Python (3)
  • SpringBoot (14)
  • Spring基础 (8)
  • thymeleaf (1)
  • 娱乐 (3)
  • 小谈 (2)
  • 常用工具 (7)
  • 技术分析集 (5)
  • 技能 (10)
  • 源码 (4)
  • 科普类 (1)
  • 算法 (9)
  • 踩坑记 (5)
文章归档
  • 2020年11月 (1)
  • 2020年7月 (1)
  • 2020年4月 (2)
  • 2020年3月 (1)
  • 2020年1月 (1)
  • 2019年11月 (1)
  • 2019年10月 (1)
  • 2019年9月 (1)
  • 2019年8月 (1)
  • 2019年7月 (2)
  • 2019年5月 (2)
  • 2019年4月 (2)
  • 2019年3月 (3)
  • 2019年2月 (2)
  • 2019年1月 (2)
  • 2018年12月 (2)
  • 2018年11月 (3)
  • 2018年10月 (3)
  • 2018年9月 (2)
  • 2018年8月 (3)
  • 2018年7月 (2)
  • 2018年5月 (1)
  • 2018年4月 (3)
  • 2018年3月 (2)
  • 2018年2月 (3)
  • 2018年1月 (5)
  • 2017年12月 (2)
  • 2017年11月 (3)
  • 2017年10月 (1)
  • 2017年9月 (1)
  • 2017年8月 (1)
  • 2017年7月 (7)
  • 2017年6月 (5)
  • 2017年5月 (1)
  • 2017年4月 (2)
  • 2017年3月 (4)
  • 2017年2月 (2)
小伙伴友链
  • 前端驿站

COPYRIGHT © 2017-2023 嘎里三分熟. ALL RIGHTS RESERVED.

浙ICP备17005575号-1

浙公网安备 33010802009043号