紀錄一下 Java 使用 AES (Advanced Encryption Standard) 加解密的範例程式碼:
import java.io.UnsupportedEncodingException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class AESTest {
public static void main(String[] args) {
try {
String seedForRandom = "TestSeed";
String plaintext = "TestPlaintext";
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
// 設定特定的隨機數種子,
// 如隨機數種子不變,就會得到相同的隨機數,
// 這裡相當於每次都使用同樣的金鑰
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(seedForRandom.getBytes("UTF-8"));
//產生 AES 金鑰
keyGenerator.init(256, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
SecretKey AES_secretKey = new SecretKeySpec(secretKey.getEncoded(), "AES");
// 取得 AES 加解密器
Cipher cipher = Cipher.getInstance("AES");
//進行加密
cipher.init(Cipher.ENCRYPT_MODE, AES_secretKey);
byte[] encryptedText_byteArray = cipher.doFinal(plaintext.getBytes("UTF-8"));
String encryptedText = new String(encryptedText_byteArray, "UTF-8");
System.out.println(encryptedText); // W?\?? ??? U]?
//對加密後的 byte[] 進行解密 (再取得一個新的 AES 加解密器來做)
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, AES_secretKey);
byte[] decryptedText_byteArray = cipher.doFinal(encryptedText_byteArray);
String decryptedText = new String(decryptedText_byteArray, "UTF-8");
System.out.println(decryptedText); // TestPlaintext
//注意!
//加密後的 byte[] (decryptedText_byteArray) 不能與 String 互轉,
//會流失一些東西,即上述的 encryptedText 會有轉不回 decryptedText_byteArray 的情況,
//如果直接拿 encryptedText 來解密會出錯,例如以下例子會產生如下錯誤:
//javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
//cipher = Cipher.getInstance("AES");
//cipher.init(Cipher.DECRYPT_MODE, AES_secretKey);
//byte[] decryptedText_byteArray2 = cipher.doFinal(encryptedText.getBytes("UTF-8"));
// ==> Execption : javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
//如上所述,替代方案可使用 base64 編碼,
//因為加密後的 byte[] (即 decryptedText_byteArray) 可用 base64 編碼來在 byte[] 和 String 之間互轉,
//如下所示:
String base64Encoded_encryptedTextcryptedText = Base64.encodeBase64String(encryptedText_byteArray);
System.out.println(base64Encoded_encryptedTextcryptedText); // V79c5vQIIP/R2wcWCVVdqA==
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, AES_secretKey);
byte[] decryptedText_byteArray2 = cipher.doFinal(Base64.decodeBase64(base64Encoded_encryptedTextcryptedText));
String decryptedText2 = new String(decryptedText_byteArray2, "UTF-8");
System.out.println(decryptedText2); // TestPlaintext
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
參考:
沒有留言 :
張貼留言