繁体   English   中英

Java AES-256-CBC无法正常工作

[英]Java AES-256-CBC not working as expected

创建了一个新类,以CBC和CTR模式使用AES测试某些内容。 因此,使用此代码,CTR可以正常工作,但是CBC返回空数组。 不知道为什么会这样,希望有人能解释一下。

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,因为这意味着发送两次相同的数据包将以相同的方式进行加密。 如果那是我想要的,那么我可以使用ECB模式。 ;)

例如,我想向EchoServer发送两次消息“ Hello World”,则服务器应该能够解密第一个接收到的数据包,而无需注意后面还有更多的数据包。 此外,客户端应能够加密和发送消息,而无需知道用户是否会提供应发送的其他数据。 不知道在这种情况下必须如何以及在何处添加填充。

Cipher.doFinal具有这种烦人的效果,在每次调用后都调用Cipher.init。 因此,如果我对“ Hello World”进行两次加密并在每次加密后调用“ doFinal”,则两个数据包(如果每个“ Hello World”都有自己的数据包)将看起来相同。

您缺少encrypt_cipher_cbc.doFinal

来自: 密码类-doFinal

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

byte[] doFinal(byte[] input)在单部分操作中加密或解密数据,或完成多部分操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM