• javax.crypto.BadPaddingException: Given final block not properly padded


    在项目中运用到了Java的AES加密,本地Windows调试一切正常,部署到Linux服务器后一直报空指针异常。

    经过一番调试,找到真正原因:javax.crypto.BadPaddingException: Given final block not properly padded

     1 package com.daredo.utils;
     2 
     3 import javax.crypto.Cipher;
     4 import javax.crypto.KeyGenerator;
     5 import javax.crypto.SecretKey;
     6 import javax.crypto.spec.SecretKeySpec;
     7 import java.security.SecureRandom;
     8 
     9 /**
    10  * Created by IntelliJ IDEA
    11  * Author: d-arlin@qq.com
    12  * Date: 2018/3/14
    13  * Time: 15:38
    14  */
    15 public class SecurityUtils {
    16 
    17     /**
    18      * 编码格式
    19      */
    20     private static String ENCODING = "UTF-8";
    21     /**
    22      * 加密算法
    23      */
    24     public static final String KEY_ALGORITHM = "AES";
    25 
    26     /**
    27      * 加密
    28      *
    29      * @param content 待加密内容
    30      * @param key     加密的密钥
    31      * @return
    32      */
    33     public static String encrypt(String content, String key) {
    34         try {
    35             KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
    36             kgen.init(128, new SecureRandom(key.getBytes(ENCODING)));
    37             SecretKey secretKey = kgen.generateKey();
    38             byte[] enCodeFormat = secretKey.getEncoded();
    39             SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
    40             Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    41             byte[] byteContent = content.getBytes(ENCODING);
    42             cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    43             byte[] byteRresult = cipher.doFinal(byteContent);
    44             StringBuffer sb = new StringBuffer();
    45             for (int i = 0; i < byteRresult.length; i++) {
    46                 String hex = Integer.toHexString(byteRresult[i] & 0xFF);
    47                 if (hex.length() == 1) hex = '0' + hex;
    48                 sb.append(hex.toUpperCase());
    49             }
    50             return sb.toString();
    51         } catch (Exception e) {
    52             e.toString();
    53         }
    54         return null;
    55     }
    56 
    57     /**
    58      * 解密
    59      *
    60      * @param content 待解密内容
    61      * @param key     解密的密钥
    62      * @return
    63      */
    64     public static String decrypt(String content, String key) {
    65         if (content.length() < 1) return null;
    66         byte[] byteRresult = new byte[content.length() / 2];
    67         for (int i = 0; i < content.length() / 2; i++) {
    68             int high = Integer.parseInt(content.substring(i * 2, i * 2 + 1), 16);
    69             int low = Integer.parseInt(content.substring(i * 2 + 1, i * 2 + 2), 16);
    70             byteRresult[i] = (byte) (high * 16 + low);
    71         }
    72         try {
    73             KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
    74             kgen.init(128, new SecureRandom(key.getBytes(ENCODING)));
    75             SecretKey secretKey = kgen.generateKey();
    76             byte[] enCodeFormat = secretKey.getEncoded();
    77             SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
    78             Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    79             cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    80             byte[] result = cipher.doFinal(byteRresult);
    81             return new String(result, ENCODING);
    82         } catch (Exception e) {
    83             e.toString();
    84         }
    85         return null;
    86     }
    87 
    88 }

    那么为什么在Windows正常,在Linux就出现异常呢?

    原因分析
    SecureRandom 实现完全随操作系统本身的內部状态,除非调用方在调用 getInstance 方法之后又调用了 setSeed 方法;

    该实现在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系统上则不同。

    解决方法

     1 package com.daredo.utils;
     2 
     3 import javax.crypto.Cipher;
     4 import javax.crypto.KeyGenerator;
     5 import javax.crypto.SecretKey;
     6 import javax.crypto.spec.SecretKeySpec;
     7 import java.security.SecureRandom;
     8 
     9 /**
    10  * Created by IntelliJ IDEA
    11  * Author: d-arlin@qq.com
    12  * Date: 2018/3/14
    13  * Time: 15:38
    14  */
    15 public class SecurityUtils {
    16 
    17     /**
    18      * 编码格式
    19      */
    20     private static final String ENCODING = "UTF-8";
    21     /**
    22      * 加密算法
    23      */
    24     public static final String KEY_ALGORITHM = "AES";
    25     /**
    26      * 签名算法
    27      */
    28     public static final String SIGN_ALGORITHMS = "SHA1PRNG";
    29 
    30     /**
    31      * 加密
    32      *
    33      * @param content 待加密内容
    34      * @param key     加密的密钥
    35      * @return
    36      */
    37     public static String encrypt(String content, String key) {
    38         try {
    39             KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
    40             SecureRandom random = SecureRandom.getInstance(SIGN_ALGORITHMS);
    41             random.setSeed(key.getBytes(ENCODING));
    42             kgen.init(128, random);
    43             SecretKey secretKey = kgen.generateKey();
    44             byte[] enCodeFormat = secretKey.getEncoded();
    45             SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
    46             Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    47             byte[] byteContent = content.getBytes(ENCODING);
    48             cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
    49             byte[] byteRresult = cipher.doFinal(byteContent);
    50             StringBuffer sb = new StringBuffer();
    51             for (int i = 0; i < byteRresult.length; i++) {
    52                 String hex = Integer.toHexString(byteRresult[i] & 0xFF);
    53                 if (hex.length() == 1) hex = '0' + hex;
    54                 sb.append(hex.toUpperCase());
    55             }
    56             return sb.toString();
    57         } catch (Exception e) {
    58             e.toString();
    59         }
    60         return null;
    61     }
    62 
    63     /**
    64      * 解密
    65      *
    66      * @param content 待解密内容
    67      * @param key     解密的密钥
    68      * @return
    69      */
    70     public static String decrypt(String content, String key) {
    71         if (content.length() < 1) return null;
    72         byte[] byteRresult = new byte[content.length() / 2];
    73         for (int i = 0; i < content.length() / 2; i++) {
    74             int high = Integer.parseInt(content.substring(i * 2, i * 2 + 1), 16);
    75             int low = Integer.parseInt(content.substring(i * 2 + 1, i * 2 + 2), 16);
    76             byteRresult[i] = (byte) (high * 16 + low);
    77         }
    78         try {
    79             KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
    80             SecureRandom random = SecureRandom.getInstance(SIGN_ALGORITHMS);
    81             random.setSeed(key.getBytes(ENCODING));
    82             kgen.init(128, random);
    83             SecretKey secretKey = kgen.generateKey();
    84             byte[] enCodeFormat = secretKey.getEncoded();
    85             SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
    86             Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
    87             cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
    88             byte[] result = cipher.doFinal(byteRresult);
    89             return new String(result, ENCODING);
    90         } catch (Exception e) {
    91             e.toString();
    92         }
    93         return null;
    94     }
    95 
    96 }

    改动的地方如代码中已标红。

  • 相关阅读:
    SE -- IO
    SE -- 多线程
    SE -- 继承
    SE -- 面对对象
    SE -- 数组
    Modern Operating System --- Chap 5.5 Clocks
    Operating System: Three Easy Pieces --- Paging: TLB (Note)
    Operating System: Three Easy Pieces --- Process (Note)
    Some Interesting Websites and Blogs
    Implement a System Call in Kernel 3.10.56 (X86_64)
  • 原文地址:https://www.cnblogs.com/Darlin356230410/p/8602674.html
Copyright © 2020-2023  润新知