How to switch from AES-256 to AES-128?

2020-08-03 06:47发布

问题:

There were many questions about AES, but I have the following problem. I'm currently using the following AES implementation to encrypt data

byte [] PRFkey = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
byte [] plaintext = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

SecretKeySpec encryptionKey=new SecretKeySpec(PRFkey, "AES");
Cipher cipher=Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
byte[] encryptedData=cipher.doFinal(plaintext);

And it turned out that result is 32-bytes (256 bits). So I'm using AES-256. This implementation is to slow for me. How can I switch to AES-128? I don't need any padding or mode of operation or key hashing.

Thank you in advance.

回答1:

You are already using 128-bit AES. This is determined by the length of the key you pass to Cipher.init(), which is sixteen bytes (128 bits) in your example.

The size of your output will depend upon your padding mode (and the size of the input data). Since you neglected to specify an operation mode or padding, your JCE provider has likely defaulted to "AES/ECB/PKCS5Padding". PKCS #5 padding will always add one additional block to the size of your output, hence you received 32 bytes of output and not 16 bytes.

Never allow your provider to select default values for you. Instead, specify the mode and padding explicitly:

Cipher cipher=Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
byte[] encryptedData=cipher.doFinal(plaintext);  // will be 16 bytes

Just remember that if you specify no padding, your input data must always be an exact multiple of 16 bytes. Also note that ECB-mode has the property that identical plaintext values will produce identical ciphertext values. This is rarely desirable in a cryptographic system.



回答2:

A similar question was asked on stack overflow here and will help provide you with the info you are looking for. An important point is that The JCA Reference Guide says that:

(Creating a Cipher Object) If no mode or padding is specified, provider-specific default values for the mode and padding scheme are used. For example, the SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider: Cipher.getInstance("DES") and Cipher.getInstance("DES/ECB/PKCS5Padding") are equivalent statements.

Thus since you are only specifying "AES" as the transformation, the default cipher for AES for Oracle JDK 7 is "AES/ECB/PKCS5Padding", link.

Additionally, the Cipher class defines the transformation "AES/ECB/NoPadding" that will get you a non-padded 16 byte value for your encryptedData. ECB is the default mode for AES, you could also choose "AES/CBC/NoPadding".