2009-08-04 8 views
8

J'implémente le cryptage/décryptage en utilisant Java Cipher et AES. Tout fonctionne bien, sauf qu'il y a 5 octets supplémentaires écrits sur l'appel de doFinal(). Donc, je me retrouve avec une chaîne correctement décodée avec 5 octets supplémentaires ajoutés.Java cipher.doFinal() écrit des octets supplémentaires

Je crois que la raison est que le bloc entier de 16 octets est écrit. Je vois 3 blocs de 16 octets écrits, dont le dernier. Le fichier chiffré d'entrée est de 64 octets. Le texte non crypté devrait être de 43 octets.

La documentation de doFinal indique qu'il peut renvoyer le nombre d'octets écrits dans le tampon de sortie. Cependant, c'est 0,16,16,16. J'ai essayé toutes les formes de doFinal et je n'ai pas changé de comportement.

Il est logique d'écrire un bloc complet, puisque c'est ainsi que fonctionnent la plupart de ces algorithmes. Cependant, si cela ne veut pas me dire la taille des données de sortie, comment suis-je censé empêcher l'excès de données?

Devrais-je utiliser un autre algorithme? AES256 est une exigence, mais je me demande si un type de bloc ou un type de remplissage différent pourrait lui permettre d'écrire le bon nombre d'octets.

Une guidance?

pour coupés sur (certains) brièveté:

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

partie commerciale de la routine de décryptage.

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

Répondre

14

Vous devez spécifier un mécanisme de remplissage lorsque vous appelez Cipher.getInstance() - de toute évidence, il doit être identique lors du cryptage et du décryptage. par exemple:

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

Sans un mécanisme de remplissage, du côté de décryptage n'a pas d'informations sur l'endroit où l'extrémité du texte en clair est (dans le dernier bloc).

+0

Génial, merci beaucoup. Cela l'a résolu. J'avais l'impression que si vous spécifiez seulement AES, vous avez le mode bloc ECB et PCKS5Padding par défaut. Devinez c'est incorrect. – wadesworld

+1

La même chose s'applique à tous les moteurs AES, y compris ceux qui ne sont pas en Java. – Cheeso

1

AES est un chiffrement par bloc , naturellement va vous donner des blocs entiers, tout comme tous les chiffrements de bloc. Pour plus d'informations, reportez-vous au Wikipedia article on AES.

Vous avez dit que vous vouliez qu'il affiche le "nombre d'octets correct". Comment avez-vous décidé quel est le nombre correct d'octets?

+1

Je pense qu'il sait que AES fait cela, la question est sur la façon d'utiliser l'API Java. – skaffman

+0

Afin de connaître la bonne taille non cryptée après décryptage, il doit écrire la taille d'origine dans le flux. –

Questions connexes