0

The following code encrypts a byte array SOURCE_DATA using AES-128 to another byte array ENCRYPTED_DATA, and then decrypts it again to DECRYPTED_DATA. With a byte array size of <= 256 bytes, the code works just fine, but if the byte array is longer, DECRYPTED_DATA only contains zeros after byte 256 and is not equal to the SOURCE_DATA array. What am I missing?

Output:

Source Data: ...fbfcfdfeff0001
Decrypted Data: ...fbfcfdfeff0000

Code:

// Create data array with size greater 256 bytes
byte[] SOURCE_DATA = new byte[257];     
for (int i=0;i<SOURCE_DATA.length; i++) {
    SOURCE_DATA[i] = (byte)((i+1) & 0xff);
}

// Init ciphers
Cipher encC = Cipher.getInstance("AES/ECB/PKCS5Padding");
Cipher decC = Cipher.getInstance("AES/ECB/PKCS5Padding");
encC.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[] {0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6}, "AES"));                  
decC.init(Cipher.DECRYPT_MODE, new SecretKeySpec(new byte[] {0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6}, "AES"));          

// Encrypt
ByteArrayOutputStream bos = new ByteArrayOutputStream();
CipherOutputStream cos = new CipherOutputStream(bos, encC);
DataOutputStream dos = new DataOutputStream(cos);

dos.write(SOURCE_DATA, 0, SOURCE_DATA.length);
dos.close();

byte[] ENCRYPTED_DATA = bos.toByteArray();

// Decrypt
ByteArrayInputStream bis = new ByteArrayInputStream(ENCRYPTED_DATA);
CipherInputStream cis = new CipherInputStream(bis, decC);
DataInputStream dis = new DataInputStream(cis);

byte[] DECRYPTED_DATA = new byte[SOURCE_DATA.length];
dis.read(DECRYPTED_DATA, 0, DECRYPTED_DATA.length);
cis.close();

System.out.println("Source Data:    "+toHex(SOURCE_DATA));
System.out.println("Decrypted Data: "+toHex(DECRYPTED_DATA));            
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
binwiederhier
  • 1,893
  • 1
  • 16
  • 23
  • 1
    "What am I missing?" The block length of the cipher algorithm? – Hot Licks Jul 03 '12 at 20:43
  • Why ECB? Why no IV? Why no authentication/MAC? – CodesInChaos Jul 03 '12 at 20:59
  • @CodeInChaos I just tried CBC with IV (according to [this post](http://stackoverflow.com/questions/1440030/how-to-implement-java-256-bit-aes-encryption-with-cbc) and the problem remains the same. – binwiederhier Jul 03 '12 at 21:15
  • @kv3980 My questions weren't about your immediate problem, but about why you chose weak crypto. – CodesInChaos Jul 03 '12 at 21:17
  • Your immediate problem is probably related to lack of flushing or partial reading. But I don't know enough about the java APIs you use to answer that. – CodesInChaos Jul 03 '12 at 21:20
  • 2
    @kv3980: welcome to your first *question* on stackoverflow :) Please don't put the answers within the question, let the site do the work - you found the "accept" button nicely it seems. – Maarten Bodewes Jul 03 '12 at 23:41

1 Answers1

1

Try using DataInputStream.readFully (i.e. you are only reading part of the result, which is why you always call InputStream.read in a while loop).

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • This was indeed the problem. The problem had nothing to do with the cipher-padding or mode of operation, but was simply related to the misuse of the `DataInputStream`. I updated the solution above. – binwiederhier Jul 03 '12 at 21:29
  • My "updated solution" was rolled back, so in short, this did the trick: `dis.readFully(DECRYPTED_DATA);` – binwiederhier Jul 11 '13 at 12:08