Gerald Tan
Gerald Tan

Reputation: 91

AES256 encryption

I'm having difficulty correctly encrypting a string in AES256. My requirements are that it needs to be AES256 and CBC, and the IV of length 24 needs to be prepended onto the encrypted string. I already have a key that is supplied and it stays the same.

My code

   public String encrypt(String value) {


    try {
        SecureRandom secureRandom = new SecureRandom();
        byte[] ivBytes = new byte[16];
        secureRandom.nextBytes(ivBytes);

        SecretKeySpec skeySpec = new SecretKeySpec(byteArray, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(ivBytes));

        byte[] encrypted = cipher.doFinal(value.getBytes());

        Log.d("encrypted", String.format("%s", encrypted.length));

        return Base64.encodeToString(ivBytes, Base64.DEFAULT) + Base64.encodeToString(encrypted, Base64.DEFAULT);


    } catch (Exception ex) {
        ex.printStackTrace();
    }

    return null;
}

Couple issues here. If I change 16 to 24 for the ivBytes, I get an error that says expected iv length is 16 not 24. I also am not sure if this code is encrypting in AES256 or AES. Any help is appreciated. Btw, value is a hexadecimal, for example, it could be something like 831684e1. Not sure if this affects encryption.

Upvotes: 0

Views: 485

Answers (2)

Gerald Tan
Gerald Tan

Reputation: 91

This is solved. I was doing the encryption correct, I just didn't realize that the Base64 appended a newline to my string. This caused the url to be incorrect. Therefore, in order to fix this, I had to use Base64.NOWRAP instead of Base64.DEFAULT

Upvotes: 0

Maarten Bodewes
Maarten Bodewes

Reputation: 94058

Couple issues here. If I change 16 to 24 for the ivBytes, I get an error that says expected iv length is 16 not 24.

That's correct. AES is only defined with a block size of 128 bits / 16 bytes. And CBC requires a random(ized) IV of a single block size.

I also am not sure if this code is encrypting in AES256 or AES.

We're not sure either, as byteArray is not specified and the AES implementation in Java/Android chooses between AES-128, -192 or -256 using the key size. Note that the key should also consist of randomized bytes (not a password encoded to bytes). Android is fine, but for Java you may need the Unlimited Crypto files for older versions of the Java Runtime Environment (JRE).

Needless to say, byteArray should be 32 bytes for AES-256.

Btw, value is a hexadecimal, for example, it could be something like 831684e1. Not sure if this affects encryption.

Generally hexadecimals is a representation of a binary value. You're probably better off first decoding the hexadecimal value, and then encrypt the binary. This would half the amount of ciphertext (and it would adhere to the principle of least surprise to other developers as well).

Currently you are using value.getBytes() which means that you would get the platform specific character encoding of the hexadecimals (UTF-8 for Android, but you'd basically get US-ASCII as hexadecimals are always encoded as one byte per character). In other words you would encode the binary value twice while no encoding is needed at all.

Upvotes: 1

Related Questions