Quel est le problème avec l'exemple suivant?
Le problème est que la première partie de la chaîne déchiffrée est absurde. Cependant, le reste va bien, je reçois ...
Result: `£eB6O�geS��i are you? Have a nice day.
@Test
public void testEncrypt() {
try {
String s = "Hello there. How are you? Have a nice day.";
// Generate key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey aesKey = kgen.generateKey();
// Encrypt cipher
Cipher encryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, aesKey);
// Encrypt
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(outputStream, encryptCipher);
cipherOutputStream.write(s.getBytes());
cipherOutputStream.flush();
cipherOutputStream.close();
byte[] encryptedBytes = outputStream.toByteArray();
// Decrypt cipher
Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
IvParameterSpec ivParameterSpec = new IvParameterSpec(aesKey.getEncoded());
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey, ivParameterSpec);
// Decrypt
outputStream = new ByteArrayOutputStream();
ByteArrayInputStream inStream = new ByteArrayInputStream(encryptedBytes);
CipherInputStream cipherInputStream = new CipherInputStream(inStream, decryptCipher);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = cipherInputStream.read(buf)) >= 0) {
outputStream.write(buf, 0, bytesRead);
}
System.out.println("Result: " + new String(outputStream.toByteArray()));
}
catch (Exception ex) {
ex.printStackTrace();
}
}
java
encryption
aes
TedTrippin
la source
la source
Réponses:
Beaucoup de gens, dont moi-même, rencontrent beaucoup de problèmes pour faire ce travail en raison du manque d'informations comme, oublier de convertir en Base64, les vecteurs d'initialisation, le jeu de caractères, etc. J'ai donc pensé à créer un code entièrement fonctionnel.
J'espère que cela vous sera utile à tous: Pour compiler, vous avez besoin d'un fichier jar Apache Commons Codec supplémentaire, disponible ici: http://commons.apache.org/proper/commons-codec/download_codec.cgi
la source
System.out.println("encrypted string:" + DatatypeConverter.printBase64Binary(encrypted));
byte[] original = cipher.doFinal(DatatypeConverter.parseBase64Binary(encrypted));
SecureRandom
Voici une solution sans
Apache Commons Codec
« sBase64
:Exemple d'utilisation:
Impressions:
la source
encrypt(String)
et nonencrypt(byte[] )
?. Le cryptage (également le décryptage) est un processus basé sur l'octet (AES l'est de toute façon). Le chiffrement prend des octets en entrée et génère des octets, tout comme le déchiffrement (cas d'espèce: l'Cipher
objet fait). Maintenant, un cas d'utilisation particulier peut être d'avoir des octets chiffrés provenant d'une chaîne, ou d'être envoyés sous forme de chaîne (pièce jointe MIME base64 pour un courrier ...), mais c'est un problème de codage d'octets, pour lequel il existe des centaines de solutions, sans aucun rapport avec AES / cryptage.Strings
puisque c'est essentiellement ce avec quoi je travaille 95% du temps et que vous finissez par convertir de toute façon.Il me semble que vous ne gérez pas correctement votre vecteur d’initialisation (IV). Cela fait longtemps que je n'ai pas lu pour la dernière fois sur AES, IVs et block chaining, mais votre ligne
ne semble pas être OK. Dans le cas d'AES, vous pouvez considérer le vecteur d'initialisation comme "l'état initial" d'une instance de chiffrement, et cet état est un peu d'informations que vous ne pouvez pas obtenir de votre clé mais du calcul réel du chiffrement de chiffrement. (On pourrait affirmer que si l'IV pouvait être extrait de la clé, alors il ne serait d'aucune utilité, car la clé est déjà donnée à l'instance de chiffrement pendant sa phase d'initialisation).
Par conséquent, vous devriez obtenir l'IV sous forme d'octet [] à partir de l'instance de chiffrement à la fin de votre chiffrement
et vous devez initialiser votre
Cipher
inDECRYPT_MODE
avec cet octet []:Ensuite, votre décryptage devrait être OK. J'espère que cela t'aides.
la source
Le IV que vous utilisez pour le décryptage est incorrect. Remplacez ce code
Avec ce code
Et cela devrait résoudre votre problème.
Vous trouverez ci-dessous un exemple de classe AES simple en Java. Je ne recommande pas d'utiliser cette classe dans les environnements de production, car elle peut ne pas prendre en compte tous les besoins spécifiques de votre application.
Notez qu'AES n'a rien à voir avec l'encodage, c'est pourquoi j'ai choisi de le gérer séparément et sans avoir besoin de bibliothèques tierces.
la source
"/NoPadding"
. CTR est un mode qui transforme AES en un chiffrement de flux, et un chiffrement de flux fonctionne sur des octets au lieu de blocs.Dans cette réponse, j'ai choisi d'aborder le thème principal «Exemple simple de chiffrement / déchiffrement de Java AES» et non la question de débogage spécifique car je pense que cela profitera à la plupart des lecteurs.
Ceci est un simple résumé de mon article de blog sur le cryptage AES en Java , je vous recommande donc de le lire avant de mettre en œuvre quoi que ce soit. Je vais cependant toujours fournir un exemple simple à utiliser et donner quelques conseils à surveiller.
Dans cet exemple, je choisirai d'utiliser le cryptage authentifié avec le mode Galois / compteur ou le mode GCM . La raison en est que dans la plupart des cas, vous voulez l' intégrité et l'authenticité en combinaison avec la confidentialité (en savoir plus dans le blog ).
Tutoriel de chiffrement / déchiffrement AES-GCM
Voici les étapes nécessaires pour crypter / décrypter avec AES-GCM avec Java Cryptography Architecture (JCA) . Ne mélangez pas avec d'autres exemples , car des différences subtiles peuvent rendre votre code totalement non sécurisé.
1. Créer une clé
Comme cela dépend de votre cas d'utilisation, je suppose le cas le plus simple: une clé secrète aléatoire.
Important:
SecureRandom
2. Créez le vecteur d'initialisation
Un vecteur d'initialisation (IV) est utilisé pour que la même clé secrète crée différents textes de chiffrement .
Important:
SecureRandom
3. Crypter avec IV et Key
Important:
CipherInputStream
lors du chiffrement de gros morceaux de donnéescipher.updateAAD(associatedData);
Plus ici.3. Sérialisation en message unique
Ajoutez simplement IV et le texte chiffré. Comme indiqué ci-dessus, l'IV n'a pas besoin d'être secrète.
Encodez éventuellement avec Base64 si vous avez besoin d'une représentation sous forme de chaîne. Utilisez l' implémentation intégrée d' Android ou de Java 8 (n'utilisez pas Apache Commons Codec - c'est une implémentation horrible). Le codage est utilisé pour "convertir" des tableaux d'octets en représentation sous forme de chaîne pour le rendre sûr ASCII, par exemple:
4. Préparez le décryptage: désérialiser
Si vous avez encodé le message, décodez-le d'abord en tableau d'octets:
Important:
5. Décrypter
Initialisez le chiffrement et définissez les mêmes paramètres qu'avec le chiffrement:
Important:
cipher.updateAAD(associatedData);
si vous les avez ajoutées lors du chiffrement.Un extrait de code fonctionnel peut être trouvé dans cet essentiel.
Notez que les implémentations Android (SDK 21+) et Java (7+) les plus récentes devraient avoir AES-GCM. Les anciennes versions peuvent en manquer. Je choisis toujours ce mode, car il est plus facile à mettre en œuvre en plus d'être plus efficace par rapport au mode similaire d' Encrypt-then-Mac (avec par exemple AES-CBC + HMAC ). Consultez cet article pour savoir comment implémenter AES-CBC avec HMAC .
la source
this is true for CBC mode but not for GCM
voulez-vous dire la partie entière, ou seulement elle n'a pas vraiment besoin d'être imprévisible?Version exécutable de l'éditeur en ligne: -
la source
C'est souvent la bonne idée de s'appuyer sur la solution standard fournie par la bibliothèque:
Cela imprime "Texte à encoder".
La solution est basée sur le Guide de référence de l'architecture de cryptographie Java et la réponse https://stackoverflow.com/a/20591539/146745 .
la source
C'est une amélioration par rapport à la réponse acceptée.
Changements:
(1) Utilisation de IV aléatoire et ajoutez-le au texte crypté
(2) Utilisation de SHA-256 pour générer une clé à partir d'une phrase de passe
(3) Aucune dépendance sur Apache Commons
la source
Une autre solution utilisant java.util.Base64 avec Spring Boot
Classe de chiffrement
Classe EncryptorController
application.properties
Exemple
http: // localhost: 8082 / cipher / encrypt / jmendoza
2h41HH8Shzc4BRU3hVDOXA ==
http: // localhost: 8082 / cipher / decrypt / 2h41HH8Shzc4BRU3hVDOXA ==
jmendoza
la source
Version optimisée de la réponse acceptée.
pas de bibliothèques tierces
inclut IV dans le message crypté (peut être public)
le mot de passe peut être de n'importe quelle longueur
Code:
Usage:
Exemple de sortie:
la source
e.printStackTrace()
on appelle un code optimisé.