2009-08-04 107 views
8

我正在使用Java Cipher和AES实现加密/解密。除了在调用doFinal()时写入5个额外的字节之外,一切都运行良好。所以,我最终得到了一个正确解码的字符串,并附加了5个额外的字节。Java cipher.doFinal()写入额外字节

我相信原因是整个16字节的块正在写入。我看到写了3个16字节块,包括最后一个。输入的加密文件是64字节。未加密的文本应该是43个字节。

doFinal的文档指出它可以返回写入输出缓冲区的字节数。但是,这是0,16,16,16。我已经尝试过所有形式的doFinal并更新并且不会改变行为。

这是有道理的,它写出一个完整的块,因为这就是大多数这些算法的操作。但是,如果它不会告诉我输出数据的大小,我该如何防止超额数据?

也许我应该使用另一种算法? AES256是一项要求,但我想知道是否有不同的块类型或填充类型可能允许它写入正确的字节数。

任何指导?

剪断的(一些)简洁:解密程序的

decryptCipher = Cipher.getInstance("AES"); 
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey); 

业务的一部分。

long bytesToRead = inputFile.length(); 

    while ((inLen = in.read(buffer)) > 0) { 
     int bytesOut = 0; 
     byte[] cryptBytes = null; 
     int outLen = cipher.getOutputSize(inLen); 
     cryptBytes = new byte[outLen]; 

     if (bytesToRead <= buffer.length) { 
      try { 
       bytesOut = cipher.doFinal(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } else 
      try { 
       bytesOut = cipher.update(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     out.write(cryptBytes, 0, bytesOut); 
     bytesToRead -= inLen; 

    } 
    try { 
     out.flush(); 
     in.close(); 
     out.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

回答

14

当您调用Cipher.getInstance()时,您必须指定填充机制 - 显然它在加密和解密时都必须相同。例如:

decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

没有填充机制,解密端没有关于明文末尾在哪里(在最后一个块内)的信息。

1

AES是分组密码,自然它会给予你整个街区,如将所有的分组密码。

查看Wikipedia article on AES了解更多信息。

你说你希望它输出“正确的字节数”。你怎么决定什么是正确的字节数?

+1

我想他知道AES会这样做,问题是关于如何使用Java API。 – skaffman 2009-08-04 07:39:19

+0

为了在解密后知道正确的未加密大小,他应该将原始大小写出到流中。 – 2009-08-04 07:45:24