javaivaes_JavaAES加密和解密教程
在本教程中,我们将看到如何使⽤JDK中的Java密码体系结构(JCA)来实现AES加密和解密。对称密钥块密码在数据加密中起重要作⽤。这意味着同⼀密钥可⽤于加密和解密。⾼级加密标准(AES)是⼀种⼴泛使⽤的对称密钥加密算法。
AES算法是⼀种迭代的对称密钥块密码,它⽀持128、192和256位的加密密钥(秘密密钥),以对128位的块中的数据进⾏加密和解密。
在AES中⽣成密钥的⽅法有两种:从随机数⽣成或从给定密码⽣成。
在第⼀种⽅法中,应该从像SecureRandom类这样的加密安全(伪)随机数⽣成器⽣成秘密密钥。为了⽣成密钥,我们可以使⽤KeyGenerator类。让我们定义⼀种⽤于⽣成⼤⼩为n(128、192和256)位的AES密钥的⽅法:
public static SecretKey generateKey(int n) throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = Instance("AES");
keyGenerator.init(n);
SecretKey key = ateKey();
return key;
}
在第⼆种⽅法中,可以使⽤基于密码的密钥派⽣功能(例如PBKDF2)从给定的密码派⽣AES秘密密钥。下⾯⽅法可通过65,536次迭代和256位密钥长度从给定密码⽣成AES密钥:
public static SecretKey getKeyFromPassword(String password, String salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = Instance("PBKDF2WithHmacSHA256");
KeySpec spec = new CharArray(), Bytes(), 65536, 256);
SecretKey secret = new ateSecret(spec)
.getEncoded(), "AES");
return secret;
}
加密字符串
要实现输⼊字符串加密,我们⾸先需要根据上⼀节⽣成密钥和初始化向量IV:
IV是伪随机值,其⼤⼩与加密的块相同。我们可以使⽤SecureRandom类⽣成随机IV。
让我们定义⼀种⽣成IV的⽅法:
public static IvParameterSpec generateIv() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
下⼀步,我们使⽤getInstance()⽅法从Cipher类创建⼀个实例。
此外,我们使⽤带有秘密密钥,IV和加密模式的init()⽅法配置密码实例。最后,我们通过调⽤doFinal()⽅法对输⼊字符串进⾏加密。此⽅法获取输⼊字节并以字节为单位返回密⽂:
public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Instance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] cipherText = cipher.Bytes());
Encoder()
.encodeToString(cipherText);
}
为了解密输⼊字符串,我们可以使⽤DECRYPT_MODE初始化密码来解密内容:
public static String decrypt(String algorithm, String cipherText, SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Instance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] plainText = cipher.Decoder()
.decode(cipherText));
return new String(plainText);
}
编写⼀个⽤于加密和解密字符串输⼊的测试⽅法:
@Test
void givenString_whenEncrypt_thenSuccess()
throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException { String input = "baeldung";
SecretKey key = ateKey(128);
IvParameterSpec ivParameterSpec = ateIv();
String algorithm = "AES/CBC/PKCS5Padding";
String cipherText = pt(algorithm, input, key, ivParameterSpec);
String plainText = AESUtil.decrypt(algorithm, cipherText, key, ivParameterSpec); Assertions.assertEquals(input, plainText);
}
加密⽂件
现在,让我们使⽤AES算法加密⽂件。步骤是相同的,但是我们需要⼀些IO类来处理⽂件。让我们加密⼀个⽂本⽂件:
public static void encryptFile(String algorithm, SecretKey key, IvParameterSpec iv,
File inputFile, File outputFile) throws IOException, NoSuchPaddingException,
NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
Cipher cipher = Instance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
java源代码加密byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = ad(buffer)) != -1) {
byte[] output = cipher.update(buffer, 0, bytesRead);
if (output != null) {
outputStream.write(output);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
inputStream.close();
outputStream.close();
}
请注意,不建议尝试将整个⽂件(尤其是⼤⽂件)读⼊内存。相反,我们⼀次加密⼀个缓冲区。
为了解密⽂件,我们使⽤类似的步骤,并使⽤DECRYPT_MODE初始化密码,如前所述。
再次,让我们定义⼀个⽤于加密和解密⽂本⽂件的测试⽅法。在这种⽅法中,我们从测试资源⽬录中读取⽂件,将其加密为⼀个名为pted的⽂件,然后将该⽂件解密为⼀个新⽂件:
@Test
void givenFile_whenEncrypt_thenSuccess()
throws NoSuchAlgorithmException, IOException, IllegalBlockSizeException,
InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException,
NoSuchPaddingException {
SecretKey key = ateKey(128);
String algorithm = "AES/CBC/PKCS5Padding";
IvParameterSpec ivParameterSpec = ateIv();
Resource resource = new ClassPathResource("");
File inputFile = File();
File encryptedFile = new File("pted");
File decryptedFile = new File("document.decrypted");
AESUtil.decryptFile(
algorithm, key, ivParameterSpec, encryptedFile, decryptedFile);
assertThat(inputFile).hasSameTextualContentAs(decryptedFile);
}
基于密码加密解密
我们可以使⽤从给定密码派⽣的密钥进⾏AES加密和解密。
为了⽣成密钥,我们使⽤getKeyFromPassword()⽅法。加密和解密步骤与字符串输⼊部分中显⽰的步骤相同。然后,我们可以使⽤实例化的密码和提供的密钥来执⾏加密。
让我们写⼀个测试⽅法:
@Test
void givenPassword_whenEncrypt_thenSuccess()
throws InvalidKeySpecException, NoSuchAlgorithmException,
IllegalBlockSizeException, InvalidKeyException, BadPaddingException,
InvalidAlgorithmParameterException, NoSuchPaddingException {
String plainText = "www.baeldung";
String password = "baeldung";
String salt = "12345678";
IvParameterSpec ivParameterSpec = ateIv();
SecretKey key = KeyFromPassword(password,salt);
String cipherText = ptPasswordBased(plainText, key, ivParameterSpec);
String decryptedCipherText = AESUtil.decryptPasswordBased(
cipherText, key, ivParameterSpec);
Assertions.assertEquals(plainText, decryptedCipherText);
}
加密对象
为了加密Java对象,我们需要使⽤SealedObject类。该对象应可序列化。让我们从定义学⽣类开始:
public class Student implements Serializable {
private String name;
private int age;
// standard setters and getters
}
接下来,让我们加密Student对象:
public static SealedObject encryptObject(String algorithm, Serializable object, SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IOException, IllegalBlockSizeException {
Cipher cipher = Instance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
SealedObject sealedObject = new SealedObject(object, cipher);
return sealedObject;
}
稍后可以使⽤正确的密码解密加密的对象:
public static Serializable decryptObject(String algorithm, SealedObject sealedObject, SecretKey key, IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, ClassNotFoundException, BadPaddingException, IllegalBlockSizeException, IOException {
Cipher cipher = Instance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
Serializable unsealObject = (Serializable) Object(cipher);
return unsealObject;
}
让我们写⼀个测试⽤例:
@Test
void givenObject_whenEncrypt_thenSuccess()
throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException, IOException, BadPaddingException, ClassNotFoundException {
Student student = new Student("Baeldung", 20);
SecretKey key = ateKey(128);
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论