Kurczaksky
Kurczaksky

Reputation: 39

Encryption with no padding does not works

Im making app for encrypting and decrypting text in AES/CBC mode. In AES/CBC/PKCS5Padding (and PKCS7Padding) everything works fine but if I set algorithm to AES/CBC/NoPadding i get "error" String as an output. What is the problem?

Class containing encrypting and decrypting functions:

public class CriptographyUtils
{
    private static final String INIT_VECTOR = "fedcba9876543210";
    private static final String ALGORITHM = "AES/CBC/NoPadding";

    public static String aesEncrypt(String key, String text)  // encrypts text (get bytes -> encrypt -> encode -> to String)
    {
        String result;

        try
        {
            IvParameterSpec iv = new IvParameterSpec(INIT_VECTOR.getBytes());
            SecretKeySpec myKey = new SecretKeySpec(fixKey(key).getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, myKey, iv);

            byte[] encryptedBytes = cipher.doFinal(text.getBytes("UTF-8"));

            result = Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            result = "error";
        }

        return result;
    }

    public static String aesDecrypt(String key, String text)  // decrypts text (get bytes -> decode -> decrypt -> to String)
    {
        String result;

        try
        {
            IvParameterSpec iv = new IvParameterSpec(INIT_VECTOR.getBytes("UTF-8"));
            SecretKeySpec myKey = new SecretKeySpec(fixKey(key).getBytes("UTF-8"), "AES"); // create new KEY in utf-8

            Cipher cipher = Cipher.getInstance(ALGORITHM); // create new cipher
            cipher.init(Cipher.DECRYPT_MODE, myKey, iv); // set cipher into decrypt mode using my KEY

            byte[] decryptedBytes = cipher.doFinal(Base64.decode(text, Base64.DEFAULT)); // get bytes -> decode -> decrypt

            result = new String(decryptedBytes);    // convert decrypted text to String
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            result = "error";
        }

        return result;
    }

    private static String fixKey(String key)
    {
        if (key.length() < 16)  // less than 128 bits
        {
            int numPad = 16 - key.length();

            for (int i = 0; i < numPad; i++)
                key += "0"; //0 pad to len 16 bytes
        }
        else if (key.length() > 16)
            key = key.substring(0, 16); //truncate to 16 bytes

        return key;
    }
}

Usage:

Encrypting:

CriptographyUtils.aesEncrypt(key, textToEncrypt)

Decrypting:

CriptographyUtils.aesDecrypt(key, textToDecrypt));

The key is:

private static final String key = "1234123412341234";

Upvotes: 1

Views: 2276

Answers (1)

zaph
zaph

Reputation: 112857

AES is a block encryption algorithm and as such must have its input be a multiple of the block size, 16-bytes for AES. Thus padding needs to be added if the data is not guaranteed to be a multiple of the block size.

Use padding: PKCS#7 is the generally used padding for AES, PKCS#5 is essentially the same.

The PKCS#5 identifier is only for AES because the coders were to lazy to add support for the PKCS#7 identifier. See PKCS#7 padding:

PKCS#5 padding is identical to PKCS#7 padding, except that it has only been defined for block ciphers that use a 64-bit (8 byte) block size. In practice the two can be used interchangeably..

Upvotes: 2

Related Questions