我一直在用基本的Java AES东西进行一些学习/实验,但我无法弄清楚哪里做错了。根据文档,doFinal()应该一次性加密/解密所有内容,而且确实做到了。但是,在解密[[带有无效的IV时,我仍然可以解密数据的[[most。为了安全起见,请告诉我测试代码在哪里搞砸了?
注意:我没有使用BC或Java无限强度加密扩展。该代码遵循The Oracle JCA Reference Guide中的示例和指南。在下面的代码中,我选择具有CFB的AES(与CBC的结果相同),生成密钥,生成IV,馈送encrypt,nuke IV,并馈送decrypt,理想情况下(如果我理解的话) CBC和CFB正确),核IV应该将解密后的输出呈现为垃圾。但这并没有...至少在我的安装中没有...
还应注意,GCM确实可以正常工作(您无疑会在下面看到注释掉的算法字符串),但令我感到困扰的是CBC和CFB是以这种方式工作的。请检查现实吗? public static void encdec() throws Exception {
// let's encrypt something!
String message = "This is a super-secret message. Don't read this message. This message will self-destruct...";
final String symmetricCipherSpec = "AES/CFB/PKCS5Padding";// "AES/GCM/NoPadding";
final String symmetricKeySpec = "AES";
System.out.println("\n\nSelecting plaintext cypher...");
Cipher cipher = Cipher.getInstance(symmetricCipherSpec);
// What did we get?
System.out.println("--> Cipher Algorithm Selected: " + cipher.getAlgorithm());
AlgorithmParameters parameters = cipher.getParameters();
System.out.println("--> Parameters for algo: " + parameters.getAlgorithm());
System.out.println("--> block size: " + cipher.getBlockSize());
final int blockSize = cipher.getBlockSize();
KeyGenerator keyGenerator = KeyGenerator.getInstance(symmetricKeySpec);
keyGenerator.init(128);
Key key = keyGenerator.generateKey();
System.out.println("\nsymmetric key = " + Hex.encodeHexString(key.getEncoded()));
// set up for encryption
int tLen = 16;
byte[] basicIV = new byte[tLen];
for (int i = 0; i < basicIV.length; i++) {
basicIV[i] = (byte) i;
}
byte[] messageToEncrypt = message.getBytes();
IvParameterSpec ivSpec = new IvParameterSpec(basicIV);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encryptedMessage = cipher.doFinal(messageToEncrypt);
System.out.println("\nencrypted = " + Hex.encodeHexString(encryptedMessage));
byte[] iv = cipher.getIV();
System.out.println("iv = " + Hex.encodeHexString(iv) + " (len=" + iv.length + ")");
// reset IV to garbage.
basicIV = new byte[tLen];
ivSpec = new IvParameterSpec(basicIV);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = cipher.doFinal(encryptedMessage);
System.out.println("\ndecrypted = " + new String(decrypted));
System.out.println("original = " + message);
System.out.println("iv = " + Hex.encodeHexString(cipher.getIV()) + " (len=" + cipher.getIV().length + ")");
}
使用不正确的IV进行解密会导致第一个纯文本块被破坏,但随后的纯文本块将是正确的。这是因为每个块都与前一个块的密文(而不是明文)进行了“异或”运算,因此在将前一个块用作IV解密当前块之前,不需要解密前一个块。