Dans cette réponse, j'ai choisi d'aborder le thème principal "Exemple simple de cryptage/décryptage AES en Java" et non la question spécifique du débogage car je pense que cela profitera à la plupart des lecteurs.
Il s'agit d'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 fournir un exemple simple à utiliser et donner quelques indications sur ce à quoi il faut faire attention.
Dans cet exemple, je vais choisir d'utiliser cryptage authentifié con Mode Galois/Compteur ou GCM mode. La raison en est que, dans la plupart des cas, vous voulez intégrité et authenticité en combinaison avec la confidentialité (lire la suite dans le blog ).
Tutoriel de chiffrement/déchiffrement AES-GCM
Voici les étapes nécessaires pour crypter/décrypter avec AES-GCM avec le Architecture cryptographique Java (JCA) . Ne pas mélanger avec d'autres exemples car des différences subtiles peuvent rendre votre code totalement insécurisé.
1. Créer une clé
Comme cela dépend de votre cas d'utilisation, je vais supposer le cas le plus simple : une clé secrète aléatoire.
SecureRandom secureRandom = new SecureRandom();
byte[] key = new byte[16];
secureRandom.nextBytes(key);
SecretKey secretKey = SecretKeySpec(key, "AES");
Important :
2. Créer le vecteur d'initialisation
Un site vecteur d'initialisation (IV) est utilisé pour qu'une même clé secrète crée des clés différentes. textes chiffrés .
byte[] iv = new byte[12]; //NEVER REUSE THIS IV WITH SAME KEY
secureRandom.nextBytes(iv);
Important :
3. Cryptage avec IV et clé
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec parameterSpec = new GCMParameterSpec(128, iv); //128 bit auth tag length
cipher.init(Cipher.ENCRYPT_MODE, secretKey, parameterSpec);
byte[] cipherText = cipher.doFinal(plainText);
Important :
- utiliser 16 octets / 128 bits étiquette d'authentification (utilisé pour vérifier l'intégrité/authenticité)
- l'étiquette d'authentification sera automatiquement ajoutée au texte chiffré (dans l'implémentation JCA).
- puisque le GCM se comporte comme un chiffrement de flux, aucun remplissage n'est nécessaire.
- utiliser
CipherInputStream
lors du chiffrement de gros morceaux de données.
- vous souhaitez que des données supplémentaires (non secrètes) soient vérifiées si elles ont été modifiées ? Vous pouvez utiliser données associées con
cipher.updateAAD(associatedData);
Plus d'informations ici.
3. Sérialisation en un seul message
Il suffit d'ajouter l'IV et le texte chiffré. Comme indiqué ci-dessus, l'IV n'a pas besoin d'être secret.
ByteBuffer byteBuffer = ByteBuffer.allocate(iv.length + cipherText.length);
byteBuffer.put(iv);
byteBuffer.put(cipherText);
byte[] cipherMessage = byteBuffer.array();
Encodage facultatif avec Base64 si vous avez besoin d'une représentation sous forme de chaîne. Soit vous utilisez Android o L'intégration de Java 8 (n'utilisez pas Apache Commons Codec - c'est une implémentation horrible). L'encodage est utilisé pour "convertir" les tableaux d'octets en représentation de chaîne de caractères afin de les rendre ASCII sûrs, par exemple :
String base64CipherMessage = Base64.getEncoder().encodeToString(cipherMessage);
4. Préparer le décryptage : Désérialiser
Si vous avez codé le message, décodez-le d'abord en tableau d'octets :
byte[] cipherMessage = Base64.getDecoder().decode(base64CipherMessage)
Important :
5. Décrypter
Initialiser le chiffrement et définir les mêmes paramètres que pour le chiffrement :
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
//use first 12 bytes for iv
AlgorithmParameterSpec gcmIv = new GCMParameterSpec(128, cipherMessage, 0, 12);
cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmIv);
//use everything from 12 bytes on as ciphertext
byte[] plainText = cipher.doFinal(cipherMessage, 12, cipherMessage.length - 12);
Important :
- n'oubliez pas d'ajouter données associées con
cipher.updateAAD(associatedData);
si vous l'avez ajouté pendant le cryptage.
Un extrait de code fonctionnel peut être trouvé dans ce gist.
Notez que les implémentations Android (SDK 21+) et Java (7+) les plus récentes devraient avoir AES-GCM. Les versions plus anciennes peuvent en être dépourvues. Je choisis toujours ce mode, car il est plus facile à implémenter en plus d'être plus efficace comparé à un mode similaire de Cryptage puis Mac (avec par exemple AES-CBC + HMAC ). Voir cet article sur la façon d'implémenter AES-CBC avec HMAC. .