Java AES cipher text size

后端 未结 2 1367
粉色の甜心
粉色の甜心 2021-02-06 17:11

I\'m using a very standard way of Java AES encryption / decryption.

byte[] key = hexStringToByteArray(\"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF\");

byte[] message = he         


        
相关标签:
2条回答
  • 2021-02-06 17:51

    There are a couple of mandatory things to get out of the way before approaching your question. One thing that I see in this code that is potentially dangerous is that the cipher isn't specified with explicit mode and padding. This means it is up to the provider defaults. If this is the provider currently distributed with Oracle's JVM, those defaults are ECB and PKCS5Padding. If those are what you want to use then specify them this way:

     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    

    The second is that ECB isn't a good choice of modes to use because it isn't very secure. CBC is a much better option since it makes use of an initialization vector.

    On to the question. The reason for the size of the encrypted text is due to the padding scheme, in this case PKCS5. The padding is necessary to ensure that the plain text is of a length that the algorithm can handle. For AES, it must be a multiple of 16 bytes. In the case where the unencrypted data's length is already a multiple of 16 bytes, the padding must add an additional 16 bytes (see jbtule's comment here). Initializing the Cipher like this produces 16 bytes of encrypted data:

    Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
    

    This requires that the unencrypted data is already a multiple of 16 bytes in length since it won't pad it at all. If it isn't, an exception is thrown.

    It might be beneficial to understand exactly what you are trying to do to give a good recommendation.

    0 讨论(0)
  • 2021-02-06 18:02

    Your cipher instance is using PKCS5Padding padding, which adds up to 16 bytes of padding to the ciphertext. There are a couple of ways to correct this:

    Option 1: Instead of using Cipher.getInstance("AES"), which uses padding, use Cipher.getInstance("AES/CBC/NoPadding"). This is NOT recommended, however, as it requires that the plaintext be a multiple of 16 bytes.

    Option 2: Use BouncyCastle as your crypto provider, and then use

    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    Cipher.getInstance("AES/CTR/NoPadding", new BouncyCastleProvider());
    

    to initialize the cipher. This uses Counter mode (CTR) instead of Cipher Block Chaining mode (CBC), and Counter mode does not require any padding. With Counter mode it is important that you use a unique initialization vector, which can be transmitted in plaintext along with the ciphertext; for example,

    byte[] IV = new byte[16];
    new SecureRandom().getBytes(IV);
    cipher.init(Cipher.ENCRYPT_MODE, key, IV);
    

    Then when decrypting the ciphertext, initialize the cipher with the same initialization vector. It is up to you how you transmit the IV, but again, it does not need to be kept secret.

    The initialization vector for Cipher Block Chaining mode should also be unique, but this is not as critical as it is for Counter mode.

    0 讨论(0)
提交回复
热议问题