简体   繁体   中英

AES-128 Encrypted String not properly padded

I'm having trouble creating an encrypted string using AES/CBC/PKCS5Padding with a 128-bit key . I have code to decrypt an encrypted string. I have an example encrypted string from another system that decrypts successfully, but when I try to create my own encrypted string it is not padded properly for some reason. When I decrypt my encrypted string it only shows the characters after the 16 byte.

All of the examples I find either assume the encryption happens first then decryption happens right after that with variables set during encryption or they are randomly generating a key, but in my case i want to use a known key.

I am really stuck so any help would be greatly appreciated, thank you very much for your time and efforts!

Example:

Original Text: 01234567891234565

Encrypted: zmb16qyYrdoW6akBdcJv7DXCzlw0qU7A2ea5q4YQWUo=

Key length: 16

Decrypted: 5 (this is the last digit in the Original Text String)

Sample Code:

package com.company.encrypt.tests;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class TestEncryptDecrypt {

    private static final String characterEncoding = "UTF-8";
    private static final String cipherTransformation = "AES/CBC/PKCS5Padding";
    private static final String aesEncryptionAlgorithm = "AES";

    public static void main(String[] args) throws Exception {
        String key1 = "1234567812345678";
        String text = "01234567891234565";
        System.out.println("Original Text: " + text);
        String encrypted = encrypt(text, key1);
        System.out.println("Encrypted: " + encrypted);
        String decrypted = decrypt(encrypted, key1);
        System.out.println("Decrypted: " + decrypted);

    }

    public static String decrypt(String encryptedText, String key) throws Exception {
        String plainText = null;

        int keyLength = key.length();
        System.out.println("Key length: " + String.valueOf(keyLength));
        byte[] encryptedTextBytes = Base64.decodeBase64(encryptedText.getBytes());
        byte[] keyBytes = key.getBytes();

        byte[] initialVector = Arrays.copyOfRange(encryptedTextBytes, 0, keyLength);
        byte[] trimmedCipherText = Arrays.copyOfRange(encryptedTextBytes, keyLength, encryptedTextBytes.length);

        try {
            Cipher cipher = Cipher.getInstance(cipherTransformation);
            SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, aesEncryptionAlgorithm);
            IvParameterSpec ivParameterSpec = new IvParameterSpec(initialVector);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

            byte[] clearText;
            clearText = cipher.doFinal(trimmedCipherText);

            plainText = new String(clearText, characterEncoding);
        } catch(NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException
                | InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return plainText;

    }

    public static String encrypt(String plainText, String encryptionKey) throws Exception {

        SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), aesEncryptionAlgorithm);
        Cipher cipher = Cipher.getInstance(cipherTransformation);
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] plainTextBytes = plainText.getBytes("UTF-8");

        byte[] encrypted = cipher.doFinal(plainTextBytes);

        return new String(Base64.encodeBase64(encrypted));
    }

}

I've noticed that in the decrypt() function, you separated the encrypted array into two parts: first 16 bytes, and the rest. You used the first 16 bytes as the IV for decryption, however, you did not prepend the 16 byte IV to the beginning of the encrypted message in encrypt() . This results in the first 16 bytes of the plaintext to be lost. I presume you assumed that doFinal() automatically does that for you, but it doesn't.

To fix this, before returning the encrypted message, prepend the IV, which can be retrieved using cipher.getIV() . You can accomplish this using the ArrayUtils.addAll() from Apache Commons Lang library, or simply write your own function to do it. Another thing to note is that the IV will always be the block size, which is 16 bytes for AES, no matter the key size.

Hope this answer helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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