当前位置: 首页 > 知识库问答 >
问题:

Java AES-256-CBC未按预期工作

令狐凌
2023-03-14
import org.junit.Before;
import org.junit.Test;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import java.security.*;
import java.util.Map;

public class AES_retest {

    private static final String plaintext = "Hallo Welt";
    private static final String key = "C0BAE23DF8B51807B3E17D21925FADF2";
    private String iv_string = "I need a initialization vector...";
    private Cipher encrypt_cipher_ctr, decrypt_cipher_ctr, encrypt_cipher_cbc, decrypt_cipher_cbc;

    @Before
    public void prepare_Test() throws GeneralSecurityException {
        byte[] tmp = new byte[16];
        System.arraycopy(iv_string.getBytes(), 0, tmp, 0, 16);

        removeCryptographyRestrictions();

        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
        //initialization vector
        IvParameterSpec iv = new IvParameterSpec(tmp);
        encrypt_cipher_cbc = Cipher.getInstance("AES/CBC/PKCS5Padding");
        encrypt_cipher_cbc.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
        decrypt_cipher_cbc = Cipher.getInstance("AES/CBC/PKCS5Padding");
        decrypt_cipher_cbc.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);
    }

    @Test
    public void multiple_CBC_update() throws BadPaddingException, IllegalBlockSizeException {
        System.out.println("Testing CBC:");
        System.out.println("Plaintext: " + plaintext);
        System.out.println("Plaintext as HEX: " + bytesToHex(plaintext.getBytes()));
        byte[] first_encryption = encrypt_cipher_cbc.update(plaintext.getBytes());
        byte[] second_encryption = encrypt_cipher_cbc.update(plaintext.getBytes());
        encrypt_cipher_cbc.doFinal();
        byte[] first_decryption = decrypt_cipher_cbc.update(first_encryption);
        byte[] second_decryption = decrypt_cipher_cbc.update(second_encryption);
        decrypt_cipher_cbc.doFinal();
        System.out.println("First encryption: " + bytesToHex(first_encryption));
        System.out.println("Second encryption: " + bytesToHex(second_encryption));
        System.out.println("First decryption: " + bytesToHex(first_decryption));
        System.out.println("Second decryption: " + bytesToHex(second_decryption));
    }
}

因为我想在我的程序中同时使用CTR和CBC,所以我想使用一个可以同时处理这两个的AES实现。对于给定的实现,这是可能的吗?

我认为这与定义的填充有关。如果我在解密中使用NoPadding,密码文本被正确解密,但填充没有被移除。如果我在解密时使用PCS5Padding,则返回一个空数组或null。第一次加密也返回一个空数组...

IntelliJ在调试时显示的图片

按照zaph的建议添加了doFinal调用,现在我得到以下错误:

Testing CBC:
Plaintext: Hallo Welt
Plaintext as HEX: 48616c6c6f2057656c74

javax.crypto.BadPaddingException: Given final block not properly padded

at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:989)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:845)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
at javax.crypto.Cipher.doFinal(Cipher.java:2048)
at AES_retest.multiple_CBC_update(AES_retest.java:117)

在我的程序的上下文中,我将通过网络套接字发送和接收加密的数据包。所以我需要独立地解密和加密每一个数据包。我不想在每个数据包的末尾调用doFinal,因为这将意味着,发送两次的相同数据包将以相同的方式加密。如果这是我想要的,那么我可以使用欧洲央行的模式。;)

例如,我想将消息“Hello World”发送两次到EchoServer时,服务器应该能够解密第一个接收到的数据包,而不会意识到后面还有更多的数据包。此外,客户端应该能够加密和发送消息,而不知道用户是否会提供应该发送的额外数据。不确定在此上下文中如何和在何处添加填充。

cipher.doFinal在每次调用之后调用cipher.init会产生这种恼人的影响。因此,如果我将“Hello World”加密两次,并在每次加密后调用“do final”,那么两个数据包(如果每个“Hello World”都有自己的数据包)看起来都是一样的。

共有1个答案

陶树
2023-03-14

您缺少encrypt_cipher_cbc.dofinal

来自:类Cipher-DoFinal

byte[]doFinal()完成多部分加密或解密操作,具体取决于此密码的初始化方式。

 类似资料:
  • 我有一些使用AES / CBC / PKCS5在Java中填充的解密数据。我正在加密两个值A和B,然后从文件中提取数据。加密的值按所述顺序写入文件。当解密各个部分的字节正确定位(通过调试确认)并且解密函数的输入正确时,没有填充问题。 加密代码: 加密时,我可以看到Cipher内部的向量在每次更新()后都按预期更新(最后一个密文是后续更新的向量。例如,加密A是我调用更新(B)时密码的向量 解密码 现

  • 我正在使用spring Roo并希望访问Controller类中的一个bean,该类在ApplicationContext.xml中具有以下配置: 配置类本身是: 在我的Controller中,我认为一个简单的Autowired注释应该可以完成这项工作 在启动过程中,spring在setSkipWeeks方法中打印消息。不幸的是,每当我在控制器中调用config.getSkipWeeks()时,它

  • 当我运行以下程序时,它只打印 然而,从Java 8的equalsIgnoreCase文档中我们发现: 如果以下至少一项为真,则两个字符c1和c2被视为相同的忽略情况: •对每个字符应用java.lang.character.ToUpperCase(char)方法会产生相同的结果 所以我的问题是为什么这个程序不打印 在这两种操作中,都使用了大写字符。

  • 我试图使用来传输我根据前面的问题设置的自定义标头。 我在文件中读到... 我的属性包括:

  • 我正在和selenium一起工作,刮一些数据。 有一个按钮在页面上,我正在点击说“Custom_Cols”。这个按钮为我打开了一个窗口,我可以在那里选择我的列。 我的问题是为什么新窗口上的元素不可见,即使我正在等待元素的可见。补充一下,我已经尝试增加延迟时间,但我还是会偶尔出现这个错误。 我的密码在这里