Java AES

Created a new class to test something with AES in CBC and CTR mode. So with this code, CTR is working fine, but CBC returns empty arrays. Not sure why this happens, hope somebody can explain that.

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));
    }
}

Because I want to use both CTR and CBC in my program I would like to use a AES implementation that can handle both at the same time. Is this possible with the given implementation?

I would suppose that it has something to do with the defined Padding. If I use NoPadding in decryption, the Cipher text is decrypted correctly, but the padding is not removed. If I use PCS5Padding on decryption, a empty array or null is returned. Also the first encryption returns a empty array...

Picture of what IntelliJ shows while debugging

Added the doFinal calls as zaph suggested, now I get following error:

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)

In the context of my program I will send and receive packets over a network socket that are encrypted. So I need to decrypt and encrypt every packet independently. I do not want to call doFinal at the end of every packet, because this would mean, that the same packet send twice would be encrypted in the same way. If that would be what I want, than I could use ECB mode. ;)

eg I want to send the message "Hello World" twice to an EchoServer, the Server should be able to decrypt the first received packet, without being aware that there are more packets following. Also the Client should be able to encrypt and send the messages, unknowing if the user will provide additional data that should be send. Not sure how and where padding hast to be added in this context.

Cipher.doFinal has this annoying affect to call Cipher.init after every call. So if I would Encrypt "Hello World" twice and call 'doFinal' after every encryption, both packets (if every "Hello World" gets its own packet) would look the same.


You are missing encrypt_cipher_cbc.doFinal .

From: Class Cipher - doFinal

byte[] doFinal() Finishes a multiple-part encryption or decryption operation, depending on how this cipher was initialized.

byte[] doFinal(byte[] input) Encrypts or decrypts data in a single-part operation, or finishes a multiple-part operation.

链接地址: http://www.djcxy.com/p/66304.html

上一篇: Visual Studio加载正确的(x86或x64)dll!

下一篇: Java AES