我已经围绕这里指定的加密和解密函数实现了一些 Package 器。
private static final Charset UTF = StandardCharsets.UTF_8;
private static String encrypt(String plainText, String aesKey) {
byte[] cipher = encryptWithPrefixIV(plainText.getBytes(UTF),
ConversionUtil.hexStringToByteArray(aesKey));
return new String(cipher, UTF);
}
public static String decrypt(String cipher, String aesKey) {
byte[] plainText = decryptWithPrefixIV(cipher.getBytes(UTF),
ConversionUtil.hexStringToByteArray(aesKey));
return new String(plainText, UTF);
}
函数hexstringtobytearray将字符串转换为十六进制格式,如 "ff"
至 11111111
. 这个功能正在运行,并且经过了很好的测试!为了简洁起见,我不包括这个函数。问题是我越来越 javax.crypto.AEADBadTagException: Tag mismatch!
异常,错误是不可修复的。代码在一段时间内运行良好,并且时不时抛出一个异常。我用于测试的代码是:
public static void main(String[] args) {
String plainText = "This is something";
String cipher = encrypt(plainText);
System.out.println(plainText.equals(decrypt(cipher)));
}
指定链接中提到的功能包括:
private static final String ENCRYPT_ALGO = "AES/GCM/NoPadding";
private static final int TAG_LENGTH_BIT = 128;
private static final int IV_LENGTH_BYTE = 12;
public static byte[] encryptWithPrefixIV(byte[] pText, byte[] aesKey) {
byte[] iv = getRandomNonce(IV_LENGTH_BYTE);
byte[] cipherText = encryptWithIV(pText, aesKey, iv);
return ByteBuffer.allocate(iv.length + cipherText.length)
.put(iv)
.put(cipherText)
.array();
}
public static byte[] encryptWithIV(byte[] pText, byte[] aesKey, byte[] iv) {
try {
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
SecretKey secret = new SecretKeySpec(aesKey, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
return cipher.doFinal(pText);
} catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
public static byte[] decryptWithPrefixIV(byte[] cText, byte[] aesKey) {
ByteBuffer bb = ByteBuffer.wrap(cText);
byte[] iv = new byte[IV_LENGTH_BYTE];
bb.get(iv);
// bb.get(iv, 0, iv.length);
byte[] cipherText = new byte[bb.remaining()];
bb.get(cipherText);
return decryptWithIV(cipherText, aesKey, iv);
}
public static byte[] decryptWithIV(byte[] cText, byte[] aesKey, byte[] iv) {
try {
Cipher cipher = Cipher.getInstance(ENCRYPT_ALGO);
SecretKey secret = new SecretKeySpec(aesKey, "AES");
cipher.init(Cipher.DECRYPT_MODE, secret, new GCMParameterSpec(TAG_LENGTH_BIT, iv));
return cipher.doFinal(cText);
} catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
public static byte[] getRandomNonce(int numBytes) {
byte[] nonce = new byte[numBytes];
new SecureRandom().nextBytes(nonce);
return nonce;
}
1条答案
按热度按时间5uzkadbs1#
它将节省我们所有人的时间,提出了一个最小的运行代码,而不是碎片。。。
第一:main函数不完整,因为它没有为encrypt和decrypt函数提供aes密钥。
第二(也是主要原因):您将加密结果转换为字符串,但这必须失败,因为密码中的许多字节是不可打印的代码(这可能解释了为什么它有时——幸运地——工作)。将输出和相应的输入更改为base64编码字符串将有助于正确的工作程序:
输出为:
完整代码: