CBC 和 CFB 模式下的 Java AES 无法正确加密? IV不被尊重?

标签 java aes jce cbc-mode

我一直在对基本的 Java AES 内容进行一些学习/实验,但我不知道我哪里做错了。根据文档, doFinal() 应该一次性加密/解密所有内容,而且它似乎确实这样做了;但是,在解密时,使用无效的 IV,我仍然可以解密大部分数据。为了安全起见,请告诉我我的测试代码到底在哪里搞砸了?

注释:我没有使用 BC 或 Java Unlimited Strength Crypto Extensions。此代码遵循 The Oracle JCA Reference Guide 中的示例和指导。在下面的代码中,我选择带有 CFB 的 AES(与 CBC 的结果相同),生成 key ,生成 IV,提供加密,核对 IV,然后提供解密,理想情况下(如果我正确理解 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 + ")");
    }

最佳答案

没关系...我对 CBC 的理解是有缺陷的;代码正在按预期工作。每Wikipedia :

Decrypting with the incorrect IV causes the first block of plaintext to be corrupt but subsequent plaintext blocks will be correct. This is because each block is XORed with the ciphertext of the previous block, not the plaintext, so one does not need to decrypt the previous block before using it as the IV for the decryption of the current one.

关于CBC 和 CFB 模式下的 Java AES 无法正确加密? IV不被尊重?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59037648/

相关文章:

java - 哪个线程正在初始化静态字段?

java - 我对该程序中使用的逻辑感到困惑,需要深入解释

c - AES CTR对称加解密

java - Java中ECC的实现

java - 配置 Oracle JDK 以使用 IBM JCE/JSSE 提供程序来实现 FIPS 合规性

java - 除了 BouncyCaSTLe,还有其他开源 JCE 库吗?

java - 为什么即使在 spring 服务类的第二种方法中 propagation=Propagation.REQUIRES_NEW 时事务也会回滚?

Java线程监控。如何找出非守护程序 Activity 线程?

java - 在 Java 中加密 Arraylist

python - 使用 Node.js AES CTR 加密并使用 PyCrypto 解密