Java AES chiffrement et le déchiffrement
Je tiens à chiffrer et de déchiffrer un mot de passe à l'aide de 128 bits de cryptage AES avec une clé 16 octets. Je suis javax.crypto.BadPaddingException
erreur lors du déchiffrement de la valeur. Ai-je raté quelque chose lors du déchiffrement?
public static void main(String args[]) {
Test t = new Test();
String encrypt = new String(t.encrypt("mypassword"));
System.out.println("decrypted value:" + t.decrypt("ThisIsASecretKey", encrypt));
}
public String encrypt(String value) {
try {
byte[] raw = new byte[]{'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y'};
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string:" + (new String(encrypted)));
return new String(skeySpec.getEncoded());
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String decrypt(String key, String encrypted) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(skeySpec.getEncoded(), "AES"));
//getting error here
byte[] original = cipher.doFinal(encrypted.getBytes());
return new String(original);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
Message d'erreur
encrypted string:�Bj�.�Ntk�F�`�
encrypted key:ThisIsASecretKey
decrypted value:null
May 25, 2012 12:54:02 PM bean.Test decrypt
SEVERE: null
javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at bean.Test.decrypt(Test.java:55)
at bean.Test.main(Test.java:24)
Enfin, je suis en utilisant la Solution suivante basée sur @QuantumMechanic réponse
public class Test {
public String encryptionKey;
public static void main(String args[]) {
Test t = new Test();
String encrypt = t.encrypt("mypassword");
System.out.println("decrypted value:" + t.decrypt(t.encryptionKey, encrypt));
}
public String encrypt(String value) {
try {
//Get the KeyGenerator
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(256);
//Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
String key = new Base64().encodeAsString(raw);
this.encryptionKey = key;
System.out.println("------------------Key------------------");
System.out.println(key);
System.out.println("--------------End of Key---------------");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
String encrypt = (new Base64()).encodeAsString(cipher.doFinal(value.getBytes()));
System.out.println("encrypted string:" + encrypt);
return encrypt;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String decrypt(String key, String encrypted) {
try {
Key k = new SecretKeySpec(Base64.getDecoder().decode(key), "AES");
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, k);
byte[] decodedValue = Base64.getDecoder().decode(encrypted);
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
} catch (IllegalBlockSizeException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (BadPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidKeyException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchPaddingException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
Vous devez vous connecter pour publier un commentaire.
Si, pour un algorithme de chiffrement par bloc, vous n'allez pas utiliser un
Cipher
de transformation qui comprend un rembourrage de régime, vous devez avoir le nombre d'octets dans le texte en clair être un multiple de la taille de bloc de l'algorithme de chiffrement.Donc, soit de combler votre texte en clair à un multiple de 16 octets (ce qui est l'AES taille de bloc), ou spécifier un protocole de remplissage lorsque vous créez votre
Cipher
objets. Par exemple, vous pourriez utiliser:À moins que vous ayez une bonne raison de ne pas utiliser un protocole de remplissage qui fait déjà partie de l'entreprise criminelle commune, la mise en œuvre. Ils ont pensé un certain nombre de subtilités et le coin des cas, vous aurez à réaliser et de gérer votre propre contraire.
Ok, votre deuxième problème est que vous utilisez
String
pour tenir le texte chiffré.En général,
sera pas ont
someBytes
etretrievedBytes
étant identiques.Si vous voulez/devez tenir le texte chiffré dans un
String
, en base64 encode le texte chiffré octets première et la construction de laString
de la base64 octets. Puis, quand vous décrypter vous aurezgetBytes()
pour obtenir le base64 octets de laString
, puis en base64 les décoder pour obtenir le vrai texte chiffré, puis de déchiffrer ce.La raison de ce problème est que la plupart (tous?) les encodages de caractères ne sont pas capables de la cartographie de l'arbitraire d'octets pour les caractères valides. Ainsi, lorsque vous créez votre
String
à partir du texte chiffré, leString
constructeur (qui s'applique un codage de caractères à activer les octets en caractères) essentiellement à jeter certains des octets parce qu'il peut faire aucun sens d'entre eux. Ainsi, lorsque vous obtenez des octets de la chaîne, ils ne sont pas les mêmes octets que vous mettez dans la chaîne.En Java (et en programmation moderne en général), vous ne pouvez pas supposer que l'un caractère = un octet, sauf si vous savez que vous avez affaire avec l'ASCII. C'est pourquoi vous devez utiliser des base64 (ou quelque chose comme ça) si vous voulez construire des chaînes de l'arbitraire d'octets.
n
octets, oùn
dépend de la taille de la clé. Regardez ceci wiki pour plus d'info.mypassword
à1234567890123456
mais j'obtiens toujours la même exception. Ma clé est 16B ainsiBASE64Encoder
etBASE64Decoder
a fait le travail. MerciIci est la mise en œuvre qui a été mentionné ci-dessus:
Essayer cela, une solution plus simple.
ThisIsASecretKey
Vous de l'état que vous souhaitez crypter/décrypter un mot de passe. Je ne suis pas sûr exactement ce que votre cas d'utilisation, mais, en général, les mots de passe ne sont pas stockés dans une forme où ils peuvent être déchiffrées. La pratique générale est de saler le mot de passe et utiliser convenablement puissant de hachage à sens unique (comme PBKDF2).
Prendre un coup d'oeil sur le lien suivant pour plus d'informations.
http://crackstation.net/hashing-security.htm
Exemple complet de chiffrement/Déchiffrement un énorme vidéo sans jeter Java
OutOfMemoryException
et à l'aide de JavaSecureRandom
pour le Vecteur d'Initialisation génération. Également représenté stocker les octets de la clé de base de données, puis de la reconstruction même clé de ces octets.https://stackoverflow.com/a/18892960/185022