2009-08-04 14 views
8

Java Cipher ve AES kullanarak şifreleme/şifre çözme yapıyorum. DoFinal() 'e yapılan çağrıda 5 ekstra bayt olması dışında her şey iyi çalışıyor. Yani, ek olarak 5 ek bayt ile doğru kodu çözülmüş bir dize ile sona.Java cipher.doFinal() extra byte yazıyor

Nedeni, 16 baytlık tüm bloğun yazılmasının gerekliliğine inanıyorum. Sonuncusu da dahil olmak üzere 3 adet 16 baytlık blok yazdım. Giriş şifreli dosya 64 bayttır. Şifrelenmemiş metin 43 bayt olmalıdır.

doFinal dokümantasyonu, çıktı arabelleğine yazılan bayt sayısını döndürebileceğini gösterir. Ancak, 0,16,16,16'dır. DoFinal'in her türünü denedim ve güncellemeyi yaptım ve davranışta hiçbir değişiklik yapmamaya başladım.

Tam anlamıyla bir blok yazması mantıklıdır, çünkü bu algoritmaların çoğu bu şekilde çalışır. Ancak, çıktı verilerinin büyüklüğünü bana söylemezse, fazla veriyi nasıl önleyebilirim?

Belki başka bir algoritma kullanmalı mıyım? AES256 bir gereksinimdir, ancak farklı bir blok tipi veya dolgu türünün doğru sayıda bayt yazmasına izin verebileceğini merak ediyorum.

Herhangi bir yönlendirme? (Bazı) kısalık için snipped

: şifre çözme rutin

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

İş parçası. Tüm blok şifrelere olacak şekilde

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(); 
    } 

cevap

14

Cipher.getInstance() öğesini çağırdığınızda bir dolgu mekanizması belirtmelisiniz - açıkçası hem şifreleme hem de şifre çözme süresinde aynı olmalıdır. örneğin: dolgu mekanizması olmadan

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

, şifre çözme yan düz metin uç (son blok içinde) olduğu hakkında herhangi bir bilgi yer alır.

+0

Harika, çok teşekkürler. Bu çözüldü. Sadece AES'yi seçtiyseniz, varsayılan olarak ECB blok modunun ve PCKS5Padding'inin aldığına dair izlenim vardı. Sanırım bu yanlış. – wadesworld

+1

aynı, Java'da olmayanlar da dahil olmak üzere tüm AES motorları için geçerlidir. – Cheeso

1

AES bir blok şifreleme olduğunu doğal olarak o, size tüm blokları vermek için gidiyor.

Daha fazla bilgi için Wikipedia article on AES'a bakın.

"Doğru bayt sayısı" vermesini istediniz. Doğru sayıda baytın ne olduğuna nasıl karar verdiniz?

+1

Sanırım AES'in bunu yaptığını, sorunun Java API'sini nasıl kullanacağını bildiğini düşünüyorum. – skaffman

+0

Şifre çözüldükten sonra doğru şifrelenmemiş boyutu bilmek için, orijinal boyutu akışa yazmalıdır. –