Comment gérer "dernier bloc incomplet dans le décryptage"
J'ai une classe simple pour essayer et enveloppez-les de chiffrement à utiliser ailleurs dans mon programme.
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
public final class StupidSimpleEncrypter
{
public static String encrypt(String key, String plaintext)
{
byte[] keyBytes = key.getBytes();
byte[] plaintextBytes = plaintext.getBytes();
byte[] ciphertextBytes = encrypt(keyBytes, plaintextBytes);
return new String(ciphertextBytes);
}
public static byte[] encrypt(byte[] key, byte[] plaintext)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec spec = new SecretKeySpec(getRawKey(key), "AES");
cipher.init(Cipher.ENCRYPT_MODE, spec);
return cipher.doFinal(plaintext);
}
catch(Exception e)
{
//some sort of problem, return null because we can't encrypt it.
Utility.writeError(e);
return null;
}
}
public static String decrypt(String key, String ciphertext)
{
byte[] keyBytes = key.getBytes();
byte[] ciphertextBytes = ciphertext.getBytes();
byte[] plaintextBytes = decrypt(keyBytes, ciphertextBytes);
return new String(plaintextBytes);
}
public static byte[] decrypt(byte[] key, byte[] ciphertext)
{
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec spec = new SecretKeySpec(getRawKey(key), "AES");
cipher.init(Cipher.DECRYPT_MODE, spec);
return cipher.doFinal(ciphertext);
}
catch(Exception e)
{
//some sort of problem, return null because we can't encrypt it.
Utility.writeError(e);
return null;
}
}
private static byte[] getRawKey(byte[] key)
{
try
{
KeyGenerator gen = KeyGenerator.getInstance("AES");
SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
rand.setSeed(key);
gen.init(256, rand);
return gen.generateKey().getEncoded();
}
catch(Exception e)
{
return null;
}
}
}
Il semble gérer le chiffrement correctement, mais pas tellement quand décryptage, qui jette un javax.crypto.IllegalBlockSizeException "dernier bloc incomplet dans le déchiffrement" à la ligne en surbrillance. Voici la trace de la pile:
Emplacement:com.xxxxxx.android.StupidSimpleEncrypter.décrypter ln:49 le dernier bloc incomplet dans le déchiffrement javax.crypto.IllegalBlockSizeException: dernier bloc incomplet dans le déchiffrement au org.bouncycastle.la jce.fournisseur de.JCEBlockCipher.engineDoFinal(JCEBlockCipher.java:711) au javax.crypto.Algorithme de chiffrement.doFinal(Cipher.java:1090) au com.xxxxxx.android.StupidSimpleEncrypter.décrypter(StupidSimpleEncrypter.java:44) au com.xxxxxx.android.StupidSimpleEncrypter.décrypter(StupidSimpleEncrypter.java:34)
J'ai fait une bonne quantité de cogner ma tête contre mon bureau pour essayer de le comprendre, mais si je reçois partout, il finit par être une autre exception. Aussi je n'arrive pas à trouver beaucoup par la recherche.
Ce qui me manque? Je vous serais reconnaissant de toute aide.
source d'informationauteur Jake Basile | 2011-01-04
Vous devez vous connecter pour publier un commentaire.
Je ne sais pas si c'est le problème avec le
IllegalBlockSizeException
mais vous ne devriez pas coder la clé comme unString
surtout sans spécifier le codage des caractères. Si vous voulez faire cela, utilisez quelque chose comme Base 64, qui est conçu pour encoder n'importe quel "binaire" des données, plutôt que d'un codage de caractères, dont seules les cartes de certains octets de caractères.La clé est, en général, va contenir les valeurs d'octets qui ne correspondent pas à un personnage de la plateforme par défaut l'encodage. Dans ce cas, lorsque vous créez le
String
l'octet sera traduit à l' "caractère de remplacement", U+FFFD (�), et la valeur correcte sera irrémédiablement perdu.D'essayer de les utiliser que de corrompre
String
représentation de la clé plus tard empêchera le texte en clair à partir de l'être récupéré; il est possible qu'il pourrait causer laIllegalBlockSizeException
mais je soupçonne une défaillance de rembourrage exception serait la plus probable.Une autre possibilité est que la source de la plate-forme et la plate-forme cible encodages de caractères sont différents, et que "décodage" le texte chiffré des résultats trop peu d'octets. Par exemple, la source de l'encodage est UTF-8, et interprète deux octets en entrée comme un seul caractère, tandis que la cible de l'encodage ISO-Latin-1, qui représente le personnage comme un seul octet.
Votre
getKeySpec()
méthode est mauvaise. Vous générer une nouvelle clé aléatoire pour crypter et décrypter les directions. Vous devez utiliser la même clé pour les deux. Vous avez sans doute remarqué que vous n'utilisez pas lekey
argument à cette méthode.Je déchirait mes cheveux plus de cela, entre une "mauvaise base 64" et "le dernier bloc incomplet" erreurs ... C'est, bien sûr, asymétrique. Voici l'essence même comment j'ai fini par le faire, qui nous l'espérons ajoute plus à la discussion que si j'ai tenté d'expliquer:
Si vous travaillez sur le tableau d'octets, alors vous devez utiliser la même taille de la mémoire tampon. Par exemple, il est bytearray dont la taille est de 1000. Après le cryptage, cette taille de devenir 2000. (ces pas la valeur réelle).
Si vous utilisez de la mémoire tampon de lire tout fichier crypté, alors vous devriez choisir la taille de tampon à 2000. J'ai résolu le même problème avec cette façon.
Pour moi, j'ai remarqué ce problème lorsque le déchiffrement des données est endommagé (il manque 1 caractère). Il aurait pu être en raison de la transmission de données via le WiFi.