JAVA实现AES 解密报错Input length must be multiple of 16 when decrypting with padded cipher
生活随笔
收集整理的這篇文章主要介紹了
JAVA实现AES 解密报错Input length must be multiple of 16 when decrypting with padded cipher
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
加密代碼
/*** 加密* * @param content 需要加密的內容* @param password 加密密碼* @return*/public static byte[] encrypt(String content, String password) {try { KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128, new SecureRandom(password.getBytes()));SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");Cipher cipher = Cipher.getInstance("AES");// 創建密碼器byte[] byteContent = content.getBytes("utf-8");cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(byteContent);return result; // 加密} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}return null;}解密代碼
/**解密* 解密的時候要傳入byte數組* @param content 待解密內容* @param password 解密密鑰* @return*/public static byte[] decrypt(byte[] content, String password) {try {KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128, new SecureRandom(password.getBytes()));SecretKey secretKey = kgen.generateKey();byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES"); Cipher cipher = Cipher.getInstance("AES");// 創建密碼器cipher.init(Cipher.DECRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(content);return result; // 加密} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}return null;}測試代碼
String content = "test";String password = "12345678";//加密System.out.println("加密前:" + content);byte[] encryptResult = encrypt(content, password);//解密byte[] decryptResult = decrypt(encryptResult,password);System.out.println("解密后:" + new String(decryptResult));輸出結果如下:
加密前:test
解密后:test
容易出錯的地方:
如果我們將測試代碼修改一下,如下:
則,系統會報出如下異常:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipherat 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*..)這主要是因為加密后的byte數組是不能強制轉換成字符串的,換言之:字符串和byte數組在這種情況下不是互逆的;要避免這種情況,我們需要做一些修訂,可以考慮將二進制數據轉換成十六進制表示,主要有如下兩個方法:
二進制轉換成16進制
/**將二進制轉換成16進制* @param buf* @return*/public static String parseByte2HexStr(byte buf[]) {StringBuffer sb = new StringBuffer();for (int i = 0; i < buf.length; i++) {String hex = Integer.toHexString(buf[i] & 0xFF);if (hex.length() == 1) {hex = '0' + hex;}sb.append(hex.toUpperCase());}return sb.toString();}16進制轉換為二進制
/**將16進制轉換為二進制* @param hexStr* @return*/public static byte[] parseHexStr2Byte(String hexStr) {if (hexStr.length() < 1)return null;byte[] result = new byte[hexStr.length()/2];for (int i = 0;i< hexStr.length()/2; i++) {int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);result[i] = (byte) (high * 16 + low);}return result;}然后,我們再修訂以上測試代碼,如下:
String content = "test";String password = "12345678";//加密System.out.println("加密前:" + content);byte[] encryptResult = encrypt(content, password);String encryptResultStr = parseByte2HexStr(encryptResult);System.out.println("加密后:" + encryptResultStr);//解密byte[] decryptFrom = parseHexStr2Byte(encryptResultStr);byte[] decryptResult = decrypt(decryptFrom,password);System.out.println("解密后:" + new String(decryptResult));測試結果如下:
加密前:test
加密后:73C58BAFE578C59366D8C995CD0B9D6D
解密后:test
另外一種加密方式
/*** 加密** @param content 需要加密的內容* @param password 加密密碼* @return*/public static byte[] encrypt2(String content, String password) {try {SecretKeySpec key = new SecretKeySpec(password.getBytes(), "AES");Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");byte[] byteContent = content.getBytes("utf-8");cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化byte[] result = cipher.doFinal(byteContent);return result; // 加密} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();}return null;} 這種加密方式有兩種限制 密鑰必須是16位的 待加密內容的長度必須是16的倍數,如果不是16的倍數,就會出如下異常: javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytesat com.sun.crypto.provider.SunJCE_f.a(DashoA13*..)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*..)要解決如上異常,可以通過補全傳入加密內容等方式進行避免。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的JAVA实现AES 解密报错Input length must be multiple of 16 when decrypting with padded cipher的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Git添加为远程仓库
- 下一篇: 工作流实战_20_flowable 任务