CBC和CFB模式下的Java AES未正确加密?四不尊重?

CBC和CFB模式下的Java AES未正确加密?四不尊重?,java,aes,jce,cbc-mode,Java,Aes,Jce,Cbc Mode,我一直在学习/实验基本的JavaAES,但我不知道我哪里做错了。根据文档,doFinal()应该一次加密/解密所有内容,而且看起来确实如此;但是,在解密时,使用无效IV,我仍然可以解密大部分数据。为了安全起见,请告诉我我到底把测试代码搞砸了在哪里 注意:我没有使用BC或Java无限强度加密扩展。此代码遵循的示例和指南来自。在下面的代码中,我选择AES with CFB(与CBC的结果相同),生成一个密钥,生成一个IV,feed encrypt,nuke the IV,feed decrypt,理

我一直在学习/实验基本的JavaAES,但我不知道我哪里做错了。根据文档,doFinal()应该一次加密/解密所有内容,而且看起来确实如此;但是,在解密时,使用无效IV,我仍然可以解密大部分数据。为了安全起见,请告诉我我到底把测试代码搞砸了在哪里

注意:我没有使用BC或Java无限强度加密扩展。此代码遵循的示例和指南来自。在下面的代码中,我选择AES with CFB(与CBC的结果相同),生成一个密钥,生成一个IV,feed encrypt,nuke the IV,feed decrypt,理想情况下(如果我正确理解CBC和CFB),nuke IV应该将解密的输出呈现为垃圾。但它没有…至少,在我的安装上没有

还应该注意的是,GCM确实工作正常(毫无疑问,您会看到下面注释掉的algo字符串),但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 + ")");
    }
public static void encdec()引发异常{
//让我们加密一些东西!
String message=“这是一条超级机密消息。不要阅读此消息。此消息将自毁…”;
最终字符串symmetricipherspec=“AES/CFB/pkcs5ppadding”/“AES/GCM/noppadding”;
最终字符串symmetricKeySpec=“AES”;
System.out.println(“\n\n选择明文密码…”);
Cipher Cipher=Cipher.getInstance(SymmetricipherSpec);
//我们得到了什么?
System.out.println(“-->选择了密码算法:”+Cipher.getAlgorithm());
AlgorithmParameters=cipher.getParameters();
System.out.println(“-->algo参数:“+Parameters.getAlgorithm());
System.out.println(“-->块大小:”+cipher.getBlockSize());
final int blockSize=cipher.getBlockSize();
KeyGenerator KeyGenerator=KeyGenerator.getInstance(symmetricKeySpec);
密钥生成器init(128);
Key=keyGenerator.generateKey();
System.out.println(“\n对称键=“+Hex.encodeHexString(key.getEncoded())”);
//设置加密
int-tLen=16;
字节[]基本值=新字节[tLen];
对于(int i=0;i
无需担心。。。我对CBC的理解有缺陷;这表明代码正在按预期工作。Per:

使用不正确的IV解密会导致第一个明文块损坏,但随后的明文块将正确。这是因为每个块都与前一块的密文(而不是明文)异或,因此在将前一块用作当前块解密的IV之前,不需要解密前一块


无所谓。。。我对CBC的理解有缺陷;这表明代码正在按预期工作。Per:

使用不正确的IV解密会导致第一个明文块损坏,但随后的明文块将正确。这是因为每个块都与前一块的密文(而不是明文)异或,因此在将前一块用作当前块解密的IV之前,不需要解密前一块


顺便说一句,关于你的
//reset IV to garbage
注释-你可能已经知道了这一点,但是Java会将你的字节数组初始化为全部0,所以不完全是垃圾/是的,我确实知道:)尽管如此,这是一个不同于原始的IV,因此可以说我的注释在我预期的结果输出中是“有希望的”!顺便说一句,关于你的
//reset IV to garbage
注释-你可能已经知道了这一点,但是Java会将你的字节数组初始化为全部0,所以不完全是垃圾/是的,我确实知道:)尽管如此,这是一个不同于原始的IV,因此可以说我的注释在我预期的结果输出中是“有希望的”!我相信大部分都是dupe,但没有找到更多,因为这不是一个真正的编程问题。另外,JCE的“无限”策略自2年前的8u161以来就已经过时了,在这之前并没有影响128位。我相信主要是dupe,但没有找到更多,因为这不是一个真正的编程问题——交叉重复。此外,JCE的“无限”策略自2年前的8u161以来就已经过时,在此之前,它不会影响128位。