Bug in Cipher ?
I ve come across what I believe is a bug in the JRE. Posting to this forum to get input from someone else and double check I m not missing something before I submit a bug report.
In a nutshell, if I pass a bytebuffer which has a position >0 to the method
doFinal(clearBuffer, outBuffer);
for the output buffer, the encryption gets corrupted every 4K bytes, for one full padding of 16 bytes. (encryption is correct for the first 4096 bytes)
If I don t advance the position, the encryption works fine.
package test;
import java.nio.ByteBuffer;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
publicclass EncryptionBug{
// set this buffer to at least 4096 bytes for the bug to appear
staticint BUFFER_LENGTH = 4111;
//set this offset to >0 for the bug to appear
staticint OUTPUT_OFFSET = 4;
publicstaticvoid main(String[] args){
byte[] encryptionKey =newbyte[16];
new Random().nextBytes(encryptionKey);
Cipher cipherEncrypt;
try{
SecretKeySpec skeySpec =new SecretKeySpec(encryptionKey,"AES");
cipherEncrypt = Cipher.getInstance("AES");
Cipher cipherDecrypt = Cipher.getInstance("AES");
cipherEncrypt.init(Cipher.ENCRYPT_MODE, skeySpec);
cipherDecrypt.init(Cipher.DECRYPT_MODE, skeySpec);
byte data[] =newbyte[BUFFER_LENGTH];
new Random().nextBytes(data);
ByteBuffer outBuffer = ByteBuffer.allocateDirect(65536);
ByteBuffer clearBuffer = outBuffer.duplicate();
clearBuffer.put(data);
clearBuffer.flip();
outBuffer.position(OUTPUT_OFFSET);
int length = cipherEncrypt.doFinal(clearBuffer, outBuffer);
byte[] encryptedBuffer =newbyte[length];
for (int i = 0; i < encryptedBuffer.length; i++){
encryptedBuffer[i] = outBuffer.get(OUTPUT_OFFSET + i);
}
byte encryptedDirect[] = cipherEncrypt.doFinal(data);
for (int i = 0; i < encryptedBuffer.length; i++){
if (encryptedDirect[i] != encryptedBuffer[i]){
System.out.println("********* corrupted index " + i +" "
+ encryptedBuffer[i] +" vs " + encryptedDirect[i]);
}
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
[4058 byte] By [
Irwina] at [2007-11-27 10:33:57]

# 3
Having looked at the Javadoc for duplicate() I seepublic abstract ByteBuffer duplicate()
Creates a new byte buffer that [b]shares[/b] this buffer's content.
The content of the new buffer will be that of this buffer. Changes to this buffer's content will be visible in the new buffer, and vice versa; the two buffers' position, limit, and mark values will be independent.
The new buffer's capacity, limit, position, and mark values will be identical to those of this buffer. The new buffer will be direct if, and only if, this buffer is direct, and it will be read-only if, and only if, this buffer is read-only.
which indicates that the two buffers will have the same capacity and that they share the same backing array. This means that your outBuffer and your clearBuffer share the same byte array.
Your cipher is reading from one buffer and writing to the other which means it is overwriting the original data! At best this seems dangerous.
Based on this, I don't think you have found a bug in Cipher.
# 4
I think your statement is incorrect.
According to the javadoc, we can share the same buffer.
http://java.sun.com/j2se/1.5.0/docs/api/javax/crypto/Cipher.html#doFinal(java.nio.ByteBuffer,%20java.nio.ByteBuffer)
Note: this method should be copy-safe, which means the input and output buffers can reference the same byte array and no unprocessed input data is overwritten when the result is copied into the output buffer.
Additionally, the fact that using a non-direct byte array works perfectly fine when sharing the same array seems to concur this fact.
The issue seems related to direct byte arrays only, when advancing position.
So far it still looks like to me a bug in the JRE.
Comments welcome
Irwina at 2007-7-28 18:25:49 >

# 5
> I think your statement is incorrect.
> According to the javadoc, we can share the same
> buffer.
> http://java.sun.com/j2se/1.5.0/docs/api/javax/crypto/C
> ipher.html#doFinal(java.nio.ByteBuffer,%20java.nio.Byt
> eBuffer)
>
> Note: this method should be copy-safe, which means
> the input and output buffers can reference the same
> byte array and no unprocessed input data is
> overwritten when the result is copied into the output
> buffer.
>
Looks like you are right BUT the use of "should be copy-safe " is interesting. I would have expected "is copy-safe" or "shall be copy-safe".
Of course the question now is - is this a problem with Cipher or a problem with ByteBuffer?