2012-07-03 153 views
0

以下代码使用AES-128将字节数组SOURCE_DATA加密到另一个字节数组ENCRYPTED_DATA,然后再次将其解密为DECRYPTED_DATA。对于< = 256字节的字节数组,代码工作得很好,但如果字节数组更长,则DECRYPTED_DATA只在字节256后面包含零,并且不等于SOURCE_DATA数组。我错过了什么?使用AES-128加密/解密字节数组> 256字节

输出:

源数据:... fbfcfdfeff0001
解密的数据:... fbfcfdfeff000

代码:

// 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));    
+1

“我错过了什么?”密码算法的块长度? –

+0

为什么选择欧洲央行?为什么没有IV?为什么没有认证/ MAC? – CodesInChaos

+0

@CodeInChaos我刚刚尝试过CBC与IV(根据[这篇文章](http://stackoverflow.com/questions/1440030/how-to-implement-java-256-bit-aes-encryption-with-cbc)和问题依然存在 – binwiederhier

回答

1

TR y使用DataInputStream.readFully(即你只是读取结果的一部分,这就是为什么你总是在一个while循环中调用InputStream.read)。

+0

这确实是个问题。该问题与密码填充或操作模式无关,但与“DataInputStream”的滥用有关。我更新了上面的解决方案。 – binwiederhier

+0

我的“更新解决方案”被回滚了,所以简而言之,这个技巧就是:'dis.readFully(DECRYPTED_DATA);' – binwiederhier