面试题答案
一键面试1. 引入必要的库
在Java中,进行AES加密和解密需要使用javax.crypto
包,这个包在Java的安全库中。一般无需额外引入,因为它是Java标准库的一部分。
2. 生成密钥
AES加密需要一个密钥,密钥长度通常为128位、192位或256位。以下是生成256位密钥的代码:
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
public class AESExample {
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
return keyGenerator.generateKey();
}
}
这里通过KeyGenerator
类的getInstance("AES")
方法获取AES密钥生成器实例,然后使用init(256)
方法初始化生成器,生成256位长度的密钥。
3. 加密数据
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
public class AESExample {
// 省略上面生成密钥的方法
public static String encrypt(String plainText, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
byte[] encryptedIVAndText = new byte[iv.length + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, iv.length);
System.arraycopy(encrypted, 0, encryptedIVAndText, iv.length, encrypted.length);
return Base64.getEncoder().encodeToString(encryptedIVAndText);
}
}
关键步骤解释:
Cipher.getInstance("AES/CBC/PKCS5Padding")
:获取AES加密算法实例,使用CBC模式和PKCS5Padding填充方式。- 生成16字节的初始向量(IV),IV用于增加加密的安全性,这里通过
SecureRandom
生成。 cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec)
:初始化Cipher为加密模式,传入密钥和IV。cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8))
:执行加密操作,将明文转换为密文。- 最后将IV和密文拼接,使用Base64编码返回。
4. 解密数据
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class AESExample {
// 省略上面生成密钥和加密的方法
public static String decrypt(String encryptedText, SecretKey secretKey) throws Exception {
byte[] decoded = Base64.getDecoder().decode(encryptedText);
byte[] iv = new byte[16];
System.arraycopy(decoded, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
byte[] encrypted = new byte[decoded.length - iv.length];
System.arraycopy(decoded, iv.length, encrypted, 0, encrypted.length);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, StandardCharsets.UTF_8);
}
}
关键步骤解释:
- 使用Base64解码接收到的密文。
- 从解码后的字节数组中提取出IV。
- 提取出真正的密文部分。
Cipher.getInstance("AES/CBC/PKCS5Padding")
:获取AES解密算法实例,同样使用CBC模式和PKCS5Padding填充方式。cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec)
:初始化Cipher为解密模式,传入密钥和IV。cipher.doFinal(encrypted)
:执行解密操作,将密文转换为明文,并返回明文的字符串形式。
5. 完整示例及测试
public class AESExample {
public static void main(String[] args) {
try {
SecretKey secretKey = generateKey();
String plainText = "Hello, AES!";
String encryptedText = encrypt(plainText, secretKey);
System.out.println("Encrypted Text: " + encryptedText);
String decryptedText = decrypt(encryptedText, secretKey);
System.out.println("Decrypted Text: " + decryptedText);
} catch (Exception e) {
e.printStackTrace();
}
}
public static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
return keyGenerator.generateKey();
}
public static String encrypt(String plainText, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
byte[] encryptedIVAndText = new byte[iv.length + encrypted.length];
System.arraycopy(iv, 0, encryptedIVAndText, 0, iv.length);
System.arraycopy(encrypted, 0, encryptedIVAndText, iv.length, encrypted.length);
return Base64.getEncoder().encodeToString(encryptedIVAndText);
}
public static String decrypt(String encryptedText, SecretKey secretKey) throws Exception {
byte[] decoded = Base64.getDecoder().decode(encryptedText);
byte[] iv = new byte[16];
System.arraycopy(decoded, 0, iv, 0, iv.length);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
byte[] encrypted = new byte[decoded.length - iv.length];
System.arraycopy(decoded, iv.length, encrypted, 0, encrypted.length);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return new String(decrypted, StandardCharsets.UTF_8);
}
}
在main
方法中,生成密钥,对一段明文进行加密,然后再对加密后的密文进行解密,并输出加密和解密后的文本。这样就完成了AES对称加密和解密的整个过程。