le dernier bloc incomplet avec CipherInputStream/CipherOutputStream, même avec un rembourrage AES/SRC/PKCS5Padding
En fait, j'ai cherché beaucoup sur internet et dans stackoverflow trop pour cela,
D'abord je n'ai pas utilisé de rembourrage dans mon chiffrement et le déchiffrement,
Mais j'ai Finalement trouvé la solution à partir d'ici
https://stackoverflow.com/a/10775577/1115788
et j'ai mis à jour mon code avec un rembourrage AES/SRC/PKCS5Padding
et le même message d'erreur est venue, et le dernier bloc n'est pas déchiffré...
Je suis en train de travailler sur ce pour les deux derniers jours, mais pas de solution trouvée
mon Crypter le Code:
package mani.droid.browsedropbox;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Crypter {
Cipher encipher;
Cipher decipher;
CipherInputStream cis;
CipherOutputStream cos;
FileInputStream fis;
byte[] ivbytes = new byte[]{(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', (byte)'o', (byte)'p'};
IvParameterSpec iv = new IvParameterSpec(ivbytes);
public boolean enCrypt(String key, InputStream is, OutputStream os)
{
try {
byte[] encoded = new BigInteger(key, 16).toByteArray();
SecretKey seckey = new SecretKeySpec(encoded, "AES");
encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
encipher.init(Cipher.ENCRYPT_MODE, seckey, iv);
cis = new CipherInputStream(is, encipher);
copyByte(cis, os);
return true;
}
catch (InvalidKeyException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public boolean deCrypt(String key, InputStream is, OutputStream os)
{
try {
byte[] encoded = new BigInteger(key, 16).toByteArray();
SecretKey seckey = new SecretKeySpec(encoded, "AES");
encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
encipher.init(Cipher.DECRYPT_MODE, seckey, iv);
cos = new CipherOutputStream(os, encipher);
copyByte(is, cos);
//cos.close();
return true;
}
catch (InvalidKeyException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
public void copyByte(InputStream is, OutputStream os) throws IOException
{
byte[] buf = new byte[8192];
int numbytes;
while((numbytes = is.read(buf)) != -1)
{
os.write(buf, 0, numbytes);
os.flush();
}
os.close();
is.close();
}
}
- Le reste du texte chiffré ok? Le chiffrement de flux d'entrée ont la désagréable habitude de mélanger les Exceptions sous le tapis, y compris les instances de
BadPaddingException
. - De vérifier la taille du fichier(?) vous écrivez et assurez-vous d'écrire tout ce correctement.
- reste de l'algorithme de chiffrement sont parfaitement décrypter, mais ce dernier bloc est manquant, de vérifier le code, je l'ai imprimé
numbytes
danscopyByte
, le résultat est quand le cryptage, tous les blocs sont en lecture, 16 bits, même pour cette dernière en blocs incomplets, mais pour le décryptage de la dernière valeur de blocage n'est pas de 16 ans, moins de 16..., Si Ma conjecture est, son collier avec la valeur null ou 0, de sorte que sa lecture d'un bloc complet au moment de chiffrement, si le fichier crypté taille est la même que ma taille de fichier d'origine pas dans plusieurs de 16bytes... - la cryptés la taille du fichier est le même que ma taille de fichier d'origine, pas de multiple de 16 bits..., plz renvoyer mon commentaire précédent...
- Essayez d'appeler
doFinal()
sur le chiffre directement pour obtenir les octets chiffrés et a éliminé les flux de questions. - En fait, je veux faire de chiffrement et de déchiffrement de fichiers, pouvez-vous svp me dire la procédure à suivre pour utiliser
doFinal()
avec les fichiers - Utiliser un petit fichier de test, de le lire dans un tableau d'octets, le passer à
do Final()
. Ou utiliserupdate()
et lire le fichier en morceaux si il est plus grand, passer le dernier morceau dedoFinal()
. - J'ai fait comme vous avez dit, lire
byte[]
à partir d'un fichier etdofinal
et écrire la sortiebyte[]
dans le fichier, son nouveau œuvres de chiffrement et de déchiffrement, de mêmeIllegalBlockException last block incomplete in decryption
Code pour Lire et Écrire des octets à partir de/vers un fichier, Lire:ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); copyByte(is, byteArray); byte[] enData = byteArray.toByteArray();
, Écrire:byte[] deData = decipher.doFinal(enData); BufferedOutputStream bos = new BufferedOutputStream(os); bos.write(deData); bos.flush(); bos.close();
- C'est la fonction
copyByte
Code:public void copyByte(InputStream is, OutputStream os) throws IOException { byte[] buf = new byte[8192]; int numbytes; while((numbytes = is.read(buf)) != -1) { Log.e("tamil", Integer.toString(numbytes)); os.write(buf, 0, numbytes); } os.flush(); is.close(); os.close(); }
Vous devez vous connecter pour publier un commentaire.
J'ai eu exactement le même problème.
La solution retenue fonctionne parce que vous avez utilisé mode de chiffrement qui ne nécessite pas de rembourrage, mais ce n'est pas une sorte de crypto-questions connexes sont fixes.
Selon la CipherOutputStream la documentation, vous devez appeler la méthode close() afin de finaliser le chiffrement correctement (c'est à dire, rembourrage bloc est ajouté).
Si vous souhaitez conserver OutputStream ouvrir même après l'appel de CipherOutputStream.la méthode close (), vous pouvez l'envelopper OutputStream du ruisseau qui ne le fermez pas. Par exemple:
Ensuite, vous pouvez utiliser:
Note le
os
flux n'est pas fermé, vous devez le faire sur votre propre lorsque cela est approprié.J'ai enfin obtenu la réponse à ma propre question, avec essais et erreurs
En fait, ici, le Conflit est je de Padding dans
encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
et Définir IV avec certaines valeurs.....,
J'ai enfin obtenu la Réponse juste remplacé l'Algorithme
À partir de:
À:
et sa a fonctionné comme un charme...., Je suggère donc de cette réponse pour les autres personnes aux prises avec ce problème, si vous avez résolu votre problème, mentionner ici, pour les autres...
J'ai vu CipherInputStream échouer avec un rembourrage aussi des problèmes. Ce comportement varié à travers les différentes versions de la JVM. Par exemple 7u55 32 bits mon code a bien fonctionné, 7u55 64 bits même code n'a pas... et j'ai aussi vu des échecs plus tard en 32 bits Jvm. Solution de contournement est d'utiliser le tableau d'octets méthodes et d'éviter de CipherInputStream.
Ne sais pas si cela est pertinent pour l'OP du problème, mais cela peut aider quelqu'un.
Lorsque vous à plusieurs reprises obtenir que
java.io.IOException: last block incomplete in decryption
indépendamment de ce que vous changer, vérifier si vous êtes encore en utilisant le fichier de certaines exécution précédente. Si votre test de lecture/écriture de code ajoute à ce fichier, vous trouverez toujours que l'exception -- sauf si vous supprimez le fichier corrompu que vous écrivez.À l'aide de CipherInputStream avec un rembourrage est possible, le passage à NoPadding est une solution de contournement, mais pas une solution.
Rembourrage est appliquée lorsque CipherInputStream atteint la fin du flux. Le point important est que vous devez appeler la méthode read() de la CipherInputStream au moins deux fois pour obtenir toutes les données.
L'exemple suivant montre comment lire un CipherInputStream avec un rembourrage: