JAVA下DES加解密在linux与windows下的兼容问题

        前段时间做了DES加密解密,采用的是javax下的DES算法,在windows下写的倒挺快,现在部署到linux上测试的时候,组长一脸严肃的找到我,声色俱厉地问我为毛测试数据都不能解密了!你写的什么JB毛算法!马上就要测试了!你给我搞神马!

   天地良心,我测的很棒的,还拉出来那个小class放到服务器上跑了啊!扶扶眼镜,赶紧下手改,找了半天发现原因如下:

   1. windows下写的的DES算法写起来很飘逸,然而在linux这个严肃的大叔面前,一切都是浮云,生成随机数的

SecureRandom secureRandom = SecureRandom.getInstance();
  需要加个限制,改成
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
 

 

        2.上面仅仅是第一步,提上去还是不行,于是我就把密钥的生成由KeyGenerator换成了SecretKeyFactory,然而一切都是浮云,linux仍然一张臭脸告诉我Given final block not properly padded。一转脸,组长的脸快拉长到东京了,赶紧继续排查

        3.第三步我想到,难道是DES补位导致的?于是把补位规则改成了"DES/ECB/PKCS5Padding",搞定了,组长啥也没说,走了。

        总结起来,DES算法对位数不足8位倍数的字符串进行加密的时候是本身是不补位的,填补方式由程序员自己定,我在windows下任性地写成了NoPadding模式,即填补方式为补充\0或者空格,然后trim;之前的测试数据是在windows下生成的,linux拿过来解密的时候一看,我擦,这是什么玩意儿,随手给扔了,报错;改成了填补方式为"DES/ECB/PKCS5Padding"也就是PKCS5Padding模式之后,windows和linux都遵循同一套填补方式,加密前对数据字节长度对8取余,余数大于0,则差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8 ,解密后就取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文。

        至于

SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
  为啥要加 "SHA1PRNG"  的问题,因为对于直接用
SecureRandom secureRandom = SecureRandom.getInstance();
  在java文档中写的是 Constructs a secure random number generator (RNG) implementing the default random number algorithm. 这样linux和windows的默认 随机数生成算法是有区别的。linux中采用的是 /dev/random生成伪随机数,当然还有 /dev/urandom这个二逼低强度的副本;windows中则不然,使用的是 CryptGenRandom RtlGenRandom 这两个算法来生成。估计这就是为何跨平台的时候需要使用"SHA1PRNG" 强随机种子算法的原因了吧!然而即便如此,java文档中提到还有一个制定伪随机数算法提供者的玩意儿,例如写成
SecureRandom secureRandom =SecureRandom.getInstance("SHA1PRNG","SUN");
  意思是告诉系统使用SUN提供的强随机种子算法,然而SUN的实现和Apache是不同的,搞不好就乱了,所以一般不用提供provider,希望系统之间不出问题就好。

 

 

        好,还有第二步的问题,使用KeyGenerator还是SecretKeyFactory的问题。讲真,这俩在解决这次问题中基本上没起作用,但有必要讲一下。密钥的生成在ORACLE的Standard Algorithm Name Documentation 中是有说明的,先说四个吧,KeyGenerator、SecretKeyFactory、KeyFactory、KeyPairGenerator。其中KeyGenerator和SecretKeyFactory都是javax.crypto包下的,主要提供给对称和非可逆加密算法,其中KeyGenerator主要提供给非可逆算法,SecretKeyFactory主要提供给对称加密算法;KeyFactory和KeyPairGenerator是在java.security包中的,主要提供给非对称加密算法的。

       OK,搞清楚了这回

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是Java中使用DES算法进行密和解密的示例代码: ```java import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class DESUtil { public static final String KEY_ALGORITHM = "DES"; public static final String CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding"; /** * DES密 * @param data 待密数据 * @param key 密钥 * @return 密后的数据 * @throws Exception */ public static byte[] encrypt(byte[] data, byte[] key) throws Exception { // 生成一个DESKeySpec对象 DESKeySpec desKeySpec = new DESKeySpec(key); // 创建一个密钥工厂 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM); // 将DESKeySpec对象转换成SecretKey对象 SecretKey secretKey = keyFactory.generateSecret(desKeySpec); // 创建一个密码器 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); // 初始化密码器为密模式,使用密钥初始化 cipher.init(Cipher.ENCRYPT_MODE, secretKey); // 密 byte[] result = cipher.doFinal(data); return result; } /** * DES解密 * @param data 待解密数据 * @param key 密钥 * @return 解密后的数据 * @throws Exception */ public static byte[] decrypt(byte[] data, byte[] key) throws Exception { // 生成一个DESKeySpec对象 DESKeySpec desKeySpec = new DESKeySpec(key); // 创建一个密钥工厂 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM); // 将DESKeySpec对象转换成SecretKey对象 SecretKey secretKey = keyFactory.generateSecret(desKeySpec); // 创建一个密码器 Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); // 初始化密码器为解密模式,使用密钥初始化 cipher.init(Cipher.DECRYPT_MODE, secretKey); // 解密 byte[] result = cipher.doFinal(data); return result; } } ``` 示例代码中使用了`DES/ECB/PKCS5Padding`算法模式和填充方式,其中: - `DES`是算法名称 - `ECB`是算法模式,ECB模式是最简单的分组模式,每个明文块独立密 - `PKCS5Padding`是填充方式,将明文数据填充至8字节的整数倍 使用示例: ```java public static void main(String[] args) throws Exception { String data = "Hello, world!"; // 待密数据 byte[] key = "12345678".getBytes(); // 密钥 byte[] encryptData = DESUtil.encrypt(data.getBytes(), key); System.out.println("密后的数据:" + new String(encryptData)); byte[] decryptData = DESUtil.decrypt(encryptData, key); System.out.println("解密后的数据:" + new String(decryptData)); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烂泥稀云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值