關於加密的一些常識如下,為上課內容
DES : Data Encryption Standard, 一種對稱式加密演算法。
美國聯邦政府於1976年定為聯邦資料處理標準(FIPS),它的
金鑰則必須是7個位元組、加密區塊(Cipher Block)固定為8個位元組。
DES目前已被視為是一種不安全的演算法。
AES : Advanced Encryption Standard, 一種對稱式加密演算法。
(美國聯邦政府於2001年納入FIPS 140-2標準),此種演算法
的Cipher Block固定為16個位元組。金鑰則必須是16個位元組、
24個位元組或32個位元組(即128個位元、192個位元或256個位元)。
ECB : Electronic CookBook, 一種資料的加密方式,這種加密方式採取
每個區塊(如8個或16個位元組)獨立加密,即加密任ㄧ區塊時與其它區塊
無關。獨立壓縮有優點也有缺點。
優點為可以由多個處理器來平行處理ㄧ個很大的資料。缺點為如果資料
的內容有重複出現的部分,而且重複資料的長度剛好與加密區塊等長,
則這些重複出現的部分經過加密後會出現相同的結果。
PKCS5Padding: 如果要加密的資料不是8個(如DES加密演算法)或
16個(如AES加密演算法)位元組的整數倍,則必須在欲加密資料的
尾端加入若干個位元組來湊成整數倍。PKCS5Padding是一種
補足不足位元組的方法。
其中老師舉了一個例子
public static void main(String[] args) {
String source = "馬總統念建中需要補數學";
String encryp = GlobalService.encryptString(source);
System.out.println("source=" + source);
System.out.println("encryp=" + encryp);
String decryp = GlobalService.decryptString(GlobalService.KEY, encryp);
System.out.println("decryp=" + decryp);
}
public static final String KEY = "KittySnoopyMicky";
public static String encryptString(String message) {
String encryptedString = "";
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
encryptedString = DatatypeConverter.printBase64Binary(cipher.doFinal(message.getBytes()));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encryptedString;
}
public static String decryptString(String key, String stringToDecrypt) {
String decryptedString = "";
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] b = DatatypeConverter.parseBase64Binary(stringToDecrypt);
decryptedString = new String(cipher.doFinal(b));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return decryptedString;
}
}
上面的是主程式,下面兩個一個是加密,一個是解密方法
所得到的結果為
原字串:123
加密後:c58c619950f96f4c04da28b48b296de0
其中老師將key加了1
public static final String KEY = "KittySnoopyMicky1";
就會產生 java.security.InvalidKeyException: Invalid AES key length: 17 bytes 的例外
原因是"金鑰則必須是16個位元組、24個位元組或32個位元組"
那如果我們把KEY改成24位元組如何?
則會產生 java.security.InvalidKeyException: Illegal key size or default parameters
這一個錯誤跟剛剛java.security.InvalidKeyException: Invalid AES key length: 17 bytes是不一樣的
這時把這段話Illegal key size or default parameters拿去google就對了
其中第一個搜尋最多人的回應, 主要是告訴你, 有東西需要去下載
然後要解壓縮放在${java.home}/jre/lib/security/
. 資料夾中就OK
選版本8的下載(老師指示用此版本...原因未知)記得按accept
原本要放得資料夾中就有local_policy和US_export_policy檔案
請把舊的檔案先加個old避免重複
然後把壓縮檔裡面兩個新的檔案解壓縮出來
接下來再run程式就不會發生問題了
其中為什麼會要這樣做?
根據上課老師透露,是美國對資訊相關規定
後來google了頗久,有一方的說法如下
" 美國規定的加密技術輸出規則中所述,有些國家是不允許輸出高強度的加密技術的,所以Java預設只支援128 bit的加密強度,
如果要用到192 bit或是256 bit時,還得去Sun原廠網站下載「JCE Unlimited Strength Jurisdiction Policy Files」。 "
如果有興趣可以來原址看看:http://richardarchitect.blogspot.tw/2007/04/aes4096-bit.html
相關網址:
http://darker50.github.io/2016/03/31/2016-03-31-AESDecondeError/
https://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
範例2:
http://cooking-java.blogspot.tw/2010/03/java-aes-encrypt.html