1. 程式人生 > >java AES 加密,報javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decryp

java AES 加密,報javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decryp

java 使用AES解密報這個異常,字面理解很容易,就是解密的字串的陣列必須是16的倍數

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher

    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:922)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:833)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
    at com.symmetric.aes.TestAES.testDecrpyt(TestAES.java:200)
    at com.symmetric.aes.TestAES.main(TestAES.java:48)

1.使用的程式碼:

package com.symmetric.aes;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

public class TestAES2 {

	private static final String enType_AES = "AES";
	private static final String pathStr = "D://aes.key";
	private static final String testStr = "AES tips you shoutld try again";
	
	
	public static void main(String[] args) {
		SecretKey genSecretKey = testGenerateKey();
		String string = genSecretKey.toString();
		
//		byte[] testEncryptBytes = testEncryptBytes(testStr, genSecretKey);
//		String testDecode = testDecrptBytes(testEncryptBytes, genSecretKey);
//		System.out.println(testDecode);  //直接運算元組,加密解密正常
		String testEncrypt = testEncrypt(testStr, genSecretKey);
		String testDecode2 = testDecrpt(testEncrypt, genSecretKey);
		System.out.println(testDecode2);
	}
	
	/**
	 * 生成金鑰
	 * 通過傳遞SecureRandom物件進行初始化
	 * 不指定種子或金鑰
	 * @return
	 */
	public static SecretKey testGenerateKey(){
		SecretKey genSecretKey = null;
		try {
			KeyGenerator kGenerator = KeyGenerator.getInstance(enType_AES);
			SecureRandom sRandom = new SecureRandom();
			kGenerator.init(sRandom);//不使用種子,每次生成的都不同
			genSecretKey = kGenerator.generateKey();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return genSecretKey;
	}
	
	
	/**
	 * 加密
	 * @param str
	 * @param genSecretKey
	 * @return
	 */
	public static byte[] testEncryptBytes(String str,SecretKey genSecretKey){
		byte encrypt [] = null;
		try {
			Cipher cipher = Cipher.getInstance(enType_AES);
			cipher.init(Cipher.ENCRYPT_MODE, genSecretKey);//加密模式,金鑰
			//cipher.update(str.getBytes());
			encrypt = cipher.doFinal(str.getBytes());
		} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		}
		return encrypt;
	}
	
	public static String testEncrypt(String str,SecretKey genSecretKey){
		byte[] testEncryptBytes = testEncryptBytes(str, genSecretKey);
		System.out.println(Arrays.toString(testEncryptBytes));
		System.out.println("加密後的陣列長度"+testEncryptBytes.length);
		return (new String(testEncryptBytes));
	}
	
	
	
	
	/**
	 * 解密
	 * @param str
	 * @param genSecretKey
	 * @return
	 */
	public static String testDecrptBytes(byte[] bytes,SecretKey genSecretKey){
		String decoderStr = null;
		try {
			Cipher cipher = Cipher.getInstance(enType_AES);
			cipher.init(Cipher.DECRYPT_MODE, genSecretKey);//解密模式
			//cipher.update(str.getBytes());
			byte[] doFinal = cipher.doFinal(bytes);
			decoderStr = new String(doFinal);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		}
		return decoderStr;
	}
	
	public static String testDecrpt(String str,SecretKey genSecretKey){
		System.out.println(Arrays.toString(str.getBytes()));
		System.out.println("陣列的大小"+str.getBytes().length);
		return testDecrptBytes(str.getBytes(), genSecretKey);
	}
}

2.分析出現此異常的情況:

如果不把加密後的陣列拼接為字串,直接返回,然後使用這個加密後的陣列進行解密沒有任何錯誤

但是把加密後的陣列拼接為字串,然後解密時在把此字串轉為陣列,就會出現此異常

3.具體分析:

發現當把位元組陣列轉為字串後,在把字串.getBytes()獲得陣列,發現兩個位元組陣列前後不一樣了,,這是報錯的位置所在

宣告:new String(byte[]),和"str".getBytes(),兩個方法使用的編碼一樣,然後換成其他編碼也出現這樣情況

3.原因:

3.1. 為什麼陣列轉字串,字串然後轉陣列會出現,前後兩個位元組陣列的值會不同,因為並不是每個位元組數和編碼集上的字元都有對應關係,如果一個位元組數在編碼集上沒有對應,編碼new String(byte[]) 後,往往解出來的會是一些亂碼無意義的符號:例如:��,

但是解碼的時候,�這個字元也是一個字元在編碼表中也有固定的位元組數用來表示,所有解碼出來的值必定是編碼表中對應的值,除非你的位元組陣列中的位元組數正好在編碼表中有對應的值,否則編碼,解碼後的位元組陣列會不一樣

誤區: 誤以為所有的位元組陣列都可以new String(),然後在通過String.getBytes()還原

3.2.再說這個異常報:解密的位元組陣列必須是16的倍數,這得從AES的原理說起,AES是把資料按16位元組分組加密的,所有如果陣列長度不是16的倍數會報錯

AES原理:AES是對資料按128位,也就是16個位元組進行分組進行加密的,每次對一組資料加密需要執行多輪。而輸入金鑰的長度可以為128、192和256位,也就是16個位元組、24個位元組和32個位元組,如果使用者輸入的金鑰長度不是這幾種長度,也會補成這幾種長度。無論輸入金鑰是多少位元組,加密還是以16位元組的資料一組來進行的,金鑰長度的不同僅僅影響加密執行的輪數。

4.解決的辦法:

4.1 可以用base64對參生的陣列進行編碼,然後在解碼,這樣不會像new String(byte[]),getBytes()那樣造成陣列前後不一致,一開始,我看到大部分人都是用base64,我也只是以為多一層編碼看起來安全一些而已,沒想到base64對陣列的處理是不會造成誤差的

4.2 就是直接返回陣列,然後再用陣列解密咯

相關推薦

java AES 加密,javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decryp

java 使用AES解密報這個異常,字面理解很容易,就是解密的字串的陣列必須是16的倍數javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting wi

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padd

jpa (2.1.0) +spring (3.2.7.RELEASE)+eclipseLink (2.6.3)+junit(4.12) 異常棧 2016-10-10 10:21:11 [ main:1933 ] - [ ERROR ] Caught ex

擾人的異常2: Input length must be multiple of 8 when decrypting with padded cipher

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipherat com.sun.crypto.provider.C

Android AES加密報錯處理:javax.crypto.IllegalBlockSizeException: error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH

xxxxx 說明 openssl length 技術分享 可能 而不是 com bsp 一、問題說明 今天寫AES加/解密功能的apk,設想是四個控件(測試用的,界面醜這種東西請忽略) 一個編緝框----用於輸入要加密的字符串 一個文本框----用於輸出加密後的字符串,和加

Java AES 加密工具類

dom .com 生成器 ogg bytes commons level result exc package com.microwisdom.utils; import java.security.NoSuchAlgorithmException; import ja

C# 實現 JAVA AES加密解密[原創]

com base gets tran con spec ole tor 技術分享 以下是網上普遍能收到的JAVA AES加密解密方法。 因為裏面用到了KeyGenerator 和 SecureRandom,但是.NET 裏面沒有這2個類。無法使用安全隨機數生成KEY。 我們

java AES 加密解密工具(Advanced Encryption Standard)

@param key block 生成 utf i++ spec res null 1、通用方法 package com.qlkj.hzd.commom.utils; import javax.crypto.*; import java.io.Unsupported

javax crypto IllegalBlockSizeException last block incomplet

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

(Android、Java) AES加密方法

Android、Java都會使用到AES加密,方法很簡單! 先匯入包 import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.crypto.Cipher; impo

C#與Java AES 加密解密

參考文件:https://www.cnblogs.com/xbzhu/p/7064642.html 前幾天對接Java介面,需要C#加密引數,Java解密。奈何網上找了一堆大同小異的加解密方法都跟Jaca加密的密文不一致,Java介面也無法解密,直到看見上面連結的第二種方法。能夠正常的解密Java加密的

java aes加密

package com.dl.utils; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec

Java AES加密 Illegal key size異常

Java實現AES加密,丟擲異常如下: java.security.InvalidKeyException: Illegal key size 原因: Illegal key size or default parameters 是指金鑰長度受限制, java執行時環境

java rsa 解密報:javax.crypto.BadPaddingException: Decryption error

Exception in thread "main" javax.crypto.BadPaddingException: Decryption error    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:3

JAVA AES加密 對應的 C# 方法

由於最近在專案中用到,之前在網上找了好多,來來回回,終於整出來了。 貼出來以後用起來方便 C# #region AES加解密 /// <summary> ///AES加密(加密步驟) ///1,加密字串得到2進位制陣

python合併矩陣錯all the input arrays must have same....和vstack() takes 1 positional arrays....

python中使用numpy合併矩陣a,b 報錯 密集(dense)矩陣的合併不報錯,然而稀疏矩陣(sparse)報錯了,即在矩陣中,多數的元素為0。 ValueError: all the input arrays must have same number of

javax.mail 錯 501 mail from address must be same as authorization user 解決方法

從一個郵箱傳送郵件 從一個郵箱傳送郵件報錯 501 mail from address must be same as authorization user,是由於獲取Session時的賬號和Message中設定的郵箱地址setFrom不一致引起的 程式碼如

elasticsearchInvalidIndexNameException[Invalid index name [demo_indexX1], must be lowercase錯誤

cut access nta and r.java ast 相同 zed strong [demo_indexX1] InvalidIndexNameException[Invalid index name [demo_indexX1], must be lowercase

python錯:TypeError: slice indices must be integers or None or have an __index__ method

宣告:本文為博主原創文章,不可轉載 https://blog.csdn.net/jjddss/article/details/73469104 在使用Python進行矩陣操作時,當內部含有除法時,會產生錯誤: TypeError: slice indices must be integers

python 之錯:TypeError: write() argument must be str, not bytes

在用 pickle.dump() 儲存二進位制檔案時,一直報錯,程式如下: with open(os.path.join(FLAGS.train_data_dir, 'files.log'), 'w') as f: pickle.dump([training_paths, testing_

faster rcnn錯:TypeError: slice indices must be integers or None or have an __index__ method

https://blog.csdn.net/qq_27637315/article/details/78849756 faster rcnn報錯:TypeError: slice indices must be integers or None or have an __index__ method