zoukankan      html  css  js  c++  java
  • 记一次文件编码出现的BUG javax.crypto.BadPaddingException: Given final block not properly padded

    1.前景:工作中需要实现一个功能,导出的数据需要加密,不能被明文看到,使用DES加密,对byte数组加密解密操作代码如下

    public class DESTool {
      static String transformation = "DESede/ECB/PKCS5Padding";
        static String algorithm = "DESede";
      public byte[] decode(byte[] srcByte, byte[] keyByte, int offset, int length) throws Exception, NoSuchAlgorithmException {
    //        DESKeySpec spec = new DESKeySpec(keyByte);
    //        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
    //        SecretKey secretKey = keyFactory.generateSecret(spec);
            SecretKey secretKey = new SecretKeySpec(keyByte, algorithm);
    //        KeySpec spec = new SecretKeySpec(keyByte, algorithm);
    //        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
    //        SecretKey secretKey = keyFactory.generateSecret(spec);
            Cipher cipher = Cipher.getInstance(transformation);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] b = cipher.doFinal(srcByte, offset, length);
            return b;
        }
      public byte[] encode(byte[] srcByte, byte[] keyByte, int offset, int length) throws Exception, NoSuchAlgorithmException {
    //        DESKeySpec spec = new DESKeySpec(keyByte);
    //        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
    //        SecretKey secretKey = keyFactory.generateSecret(spec);
            SecretKey secretKey = new SecretKeySpec(keyByte, algorithm);
    //        KeySpec spec = new SecretKeySpec(keyByte, algorithm);
    //        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
    //        SecretKey secretKey = keyFactory.generateSecret(spec);
            Cipher cipher = Cipher.getInstance(transformation);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] b = cipher.doFinal(srcByte, offset, length);
            return b;
        }
    }

    2.在使用如上方法进行加解密时,由于文件大小是不确定的,所以使用分批次加解密,一次加解密50*1024个byte

    3.自主测试没有问题,但是测试环境上出现问题,堆栈信息如下

    Caused by: 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.DESedeCipher.engineDoFinal(DashoA13*..)
        at javax.crypto.Cipher.doFinal(DashoA13*..)

    4.网上搜索答案都是说一些linux上SecretKey获取的问题,但是和本人工作中的状况不符,本人工作中windows开发环境上加密导出的文件去测试环境导入是可以正常导入的,并且本人写了测试类,编译成class文件后去测试环境执行class文件,加解密没有问题,所以这个可能性排除

    5.于是我要来了测试环境的数据库连接信息,本地连接测试数据库,同时导出未加密的明文文件和加密的密文文件,之后对明文文件加密之后和密文文件逐字节进行对比,对比结果完全一样

    6.最后想到加密解密是按自己进行的,会不会是加解密的字节长度导致的,于是我把测试类中加密明文文件时使用的字节数组长度设置为5*1024,而不是50*1024,之后加密,再和密文文件逐字节对比,果然出现了不同,

    7.最后经测试,需加密的字节长度和加密结果的字节长度存在以下关系:加密结果字节长度 = (需加密字节长度/8)* 8 + 8;于是我把解密时字节长度改为了50*1024+8,问题解决

    8.结论:加密过程中字节长度可能会变化,因此解密时字节长度应该和加密时字节长度存在一定的相关关系,不能随便设置。

  • 相关阅读:
    ArrayList、Vector、LinkedList的区别联系?
    TFFS格式化到创建成功过程
    C语言中的far关键字
    Android编码规范05
    微信小程序开发总结
    1-2 Mobx 入门实践之TodoList(官方Demo)
    1-1、create-react-app 配置 mobx
    3-0 js基础 语言特性及性能优化
    2-9 js基础 cookie封装
    2-8 js基础 jsonp封装
  • 原文地址:https://www.cnblogs.com/fiftyonesteps/p/11245517.html
Copyright © 2011-2022 走看看