Why is the ciphertext 32 bytes long when encrypting 16 bytes with AES?

强颜欢笑 提交于 2019-11-30 05:06:41

If you look at the specification section 5 then you can see that the input, output and state are all 128 bit. The only thing that varies is the size of the key: 128, 196 or 256 bits. So encrypting a 16 byte input state will yield a 16 byte output state.

Are you sure you aren't mixing it up with the length in hexadecimal notation or similar? If it is in hexadecimal notation then it's correct because for each byte two characters are needed to represent it: 00-FF (for the range 0-255).

Another way you can test if the encryption is correct is by doing the equivalent decryption, see if it matches the plaintext input string.

Anyway, it does the correct thing. Here's a test:

public static void main(String[] args) {
  try {
    String plaintext = "Hello world", key = "test";
    String ciphertext = encrypt(key, plaintext);
    String plaintext2 = decrypt(key, ciphertext);
    System.out.println("Encrypting '" + plaintext +
                       "' yields: (" + ciphertext.length() + ") " + ciphertext);
    System.out.println("Decrypting it yields: " + plaintext2);
  }
  catch (Exception ex) {
      ex.printStackTrace();
  }
}

Which yields:

Encrypting 'Hello world' yields: (32) 5B68978D821FCA6022D4B90081F76B4F

Decrypting it yields: Hello world

AES defaults to ECB mode encryption with PKCS#7 compatible padding mode (for all providers observed so far). ECB and CBC mode encryption require padding if the input is not precisely a multiple of the blocksize in size, with 16 being the block size of AES in bytes.

Unfortunately there might be no way for the unpadding mechanism to distinguish between padding and data; the data itself may represent valid padding. So for 16 bytes of input you will get another 16 bytes of padding. Padding modes that are deterministic such as PKCS#7 always pad with 1 to [blocksize] bytes.

If you look at int output = cipher.getOutputSize(16); you will get back 32 bytes. Use "AES/ECB/NoPadding" during decipher to see the padding bytes (e.g. 4D61617274656E20426F64657765732110101010101010101010101010101010).

You are better off when you fully specify the algorithm ("AES/CBC/PKCS5Padding" is used normally). Otherwise you will keep guessing which mode is actually used.

Note that using ECB mode is not safe as an attacker can retrieve information from the cipher text. Identical blocks of plain text encode to identical blocks of cipher text.

package com.cipher;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

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;

public class Encrypt {

    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
        // TODO Auto-generated method stub
String s="You are doing encryption at deep level";
SecureRandom sr=SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(s.getBytes());
byte[] k=new byte[128/8];
sr.nextBytes(k);
SecretKeySpec spec=new SecretKeySpec(k,"AES");
byte[] iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
IvParameterSpec ivs=new IvParameterSpec(iv);
Cipher cps=Cipher.getInstance("AES/CBC/PKCS5Padding");
cps.init(Cipher.ENCRYPT_MODE,spec,ivs);
byte[] iv2=cps.doFinal(s.getBytes());
System.out.println("En"+iv2);
Cipher cpr=Cipher.getInstance("AES/CBC/PKCS5Padding");
cpr.init(Cipher.DECRYPT_MODE, spec,ivs);
byte[] iv3=cpr.doFinal(iv2);
String ds=new String(iv3);
System.out.println(ds);


    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!