C'est la première page qui s'affiche via Google et les vulnérabilités de sécurité dans toutes les implémentations me font grincer des dents, alors je publie ceci pour ajouter des informations concernant le cryptage pour les autres, car cela remonte à 7 ans depuis la publication originale. Je suis titulaire d'une maîtrise en génie informatique et j'ai passé beaucoup de temps à étudier et à apprendre la cryptographie, donc je jette mes deux cents pour rendre Internet plus sûr.
Notez également qu'une grande partie de la mise en œuvre peut être sécurisée pour une situation donnée, mais pourquoi les utiliser et éventuellement faire une erreur accidentelle? Utilisez les outils les plus puissants dont vous disposez, sauf si vous avez une raison spécifique de ne pas le faire. Dans l'ensemble, je conseille vivement d'utiliser une bibliothèque et de rester à l'écart des détails essentiels si vous le pouvez.
MISE À JOUR 4/5/18: J'ai réécrit certaines parties pour les rendre plus simples à comprendre et j'ai changé la bibliothèque recommandée de Jasypt vers la nouvelle bibliothèque de Google Tink , je recommanderais de supprimer complètement Jasypt d'une configuration existante.
Préface
Je décrirai ci-dessous les bases de la cryptographie symétrique sécurisée et soulignerai les erreurs courantes que je vois en ligne lorsque les gens implémentent eux-mêmes la cryptographie avec la bibliothèque Java standard. Si vous souhaitez simplement ignorer tous les détails de la nouvelle bibliothèque de Google, Tink, importez-la dans votre projet et utilisez le mode AES-GCM pour tous vos cryptages et vous serez en sécurité.
Maintenant, si vous voulez apprendre les détails sur la façon de crypter en java, lisez la suite :)
Bloquer les chiffrements
Tout d'abord, vous devez choisir un chiffrement par bloc à clé symétrique. Un chiffrement par bloc est une fonction / un programme informatique utilisé pour créer un pseudo-aléatoire. Le pseudo-aléatoire est un faux hasard qu'aucun ordinateur autre qu'un ordinateur quantique ne serait capable de faire la différence entre celui-ci et le vrai hasard. Le Block Cipher est comme la pierre angulaire de la cryptographie, et lorsqu'il est utilisé avec différents modes ou schémas, nous pouvons créer des cryptages.
En ce qui concerne les algorithmes de chiffrement par blocs disponibles aujourd'hui, assurez-vous de ne JAMAIS , je répète, de ne JAMAIS utiliser DES , je dirais même de ne JAMAIS utiliser 3DES . Le seul Block Cipher que même la version NSA de Snowden a pu vérifier comme étant vraiment aussi proche que possible du pseudo-aléatoire est AES 256 . Il existe également AES 128; la différence est que AES 256 fonctionne dans des blocs de 256 bits, tandis que AES 128 fonctionne dans 128 blocs. Dans l'ensemble, AES 128 est considéré comme sécurisé bien que certaines faiblesses aient été découvertes, mais 256 est aussi solide que possible.
Fait amusant, le DES a été brisé par la NSA lors de sa création et a en fait gardé un secret pendant quelques années. Bien que certaines personnes affirment toujours que 3DES est sécurisé, il existe de nombreux articles de recherche qui ont trouvé et analysé les faiblesses de 3DES .
Modes de cryptage
Le chiffrement est créé lorsque vous prenez un chiffrement par bloc et utilisez un schéma spécifique afin que le caractère aléatoire soit combiné avec une clé pour créer quelque chose qui est réversible tant que vous connaissez la clé. Ceci est appelé un mode de cryptage.
Voici un exemple de mode de cryptage et du mode le plus simple connu sous le nom de ECB, juste pour que vous puissiez comprendre visuellement ce qui se passe:
Les modes de cryptage que vous verrez le plus souvent en ligne sont les suivants:
ECB CTR, CBC, GCM
Il existe d'autres modes en dehors de ceux énumérés et les chercheurs travaillent toujours vers de nouveaux modes pour améliorer les problèmes existants.
Passons maintenant aux implémentations et à ce qui est sécurisé. N'utilisez JAMAIS ECB, c'est mauvais pour cacher les données répétitives comme le montre le célèbre pingouin Linux .
Lors de l'implémentation en Java, notez que si vous utilisez le code suivant, le mode ECB est défini par défaut:
Cipher cipher = Cipher.getInstance("AES");
... DANGER CECI EST UNE VULNÉRABILITÉ! et malheureusement, cela se voit partout dans StackOverflow et en ligne dans des tutoriels et des exemples.
Nonces et IV
En réponse au problème rencontré avec le mode ECB, des noms également appelés IV ont été créés. L'idée est que nous générons une nouvelle variable aléatoire et l'attachons à chaque cryptage afin que lorsque vous cryptez deux messages identiques, ils sortent différents. La beauté derrière cela est qu'un IV ou nonce est de notoriété publique. Cela signifie qu'un attaquant peut y avoir accès, mais tant qu'il n'a pas votre clé, il ne peut rien faire avec cette connaissance.
Les problèmes courants que je vais voir sont que les gens définiront l'IV comme une valeur statique comme dans la même valeur fixe dans leur code. et voici le piège des IV au moment où vous en répétez un, vous compromettez en fait toute la sécurité de votre cryptage.
Générer une IV aléatoire
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
Remarque: SHA1 est cassé mais je n'ai pas pu trouver comment implémenter correctement SHA256 dans ce cas d'utilisation, donc si quelqu'un veut essayer de le mettre à jour, ce serait génial! De plus, les attaques SHA1 ne sont toujours pas conventionnelles car cela peut prendre quelques années sur un énorme cluster pour se fissurer. Consultez les détails ici.
Implémentation CTR
Aucun remplissage n'est requis pour le mode CTR.
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
Mise en œuvre de CBC
Si vous choisissez d'implémenter le mode CBC, faites-le avec PKCS7Padding comme suit:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Vulnérabilité CBC et CTR et pourquoi vous devriez utiliser GCM
Bien que certains autres modes tels que CBC et CTR soient sécurisés, ils se heurtent au problème où un attaquant peut retourner les données chiffrées, en modifiant leur valeur une fois déchiffrées. Alors disons que vous cryptez un message bancaire imaginaire "Sell 100", votre message crypté ressemble à ce "eu23ng", l'attaquant change un bit en "eu53ng" et tout d'un coup, une fois votre message déchiffré, il se lit comme "Sell 900".
Pour éviter cela, la majorité d'Internet utilise GCM, et chaque fois que vous voyez HTTPS, ils utilisent probablement GCM. GCM signe le message chiffré avec un hachage et vérifie que le message n'a pas été modifié à l'aide de cette signature.
J'éviterais de mettre en œuvre GCM en raison de sa complexité. Vous feriez mieux d'utiliser la nouvelle bibliothèque de Googles Tink, car là encore, si vous répétez accidentellement une IV, vous compromettez la clé dans le cas de GCM, qui est la faille de sécurité ultime. De nouveaux chercheurs travaillent sur des modes de cryptage IV résistants aux répétitions où même si vous répétez l'IV, la clé n'est pas en danger, mais cela n'est pas encore devenu courant.
Maintenant, si vous souhaitez implémenter GCM, voici un lien vers une belle implémentation GCM . Cependant, je ne peux pas assurer la sécurité ou si elle est correctement mise en œuvre, mais cela fait tomber la base. Notez également qu'avec GCM, il n'y a pas de rembourrage.
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
Clés vs mots de passe
Une autre note très importante, c'est que lorsqu'il s'agit de cryptographie, une clé et un mot de passe ne sont pas les mêmes choses. Une clé en cryptographie doit avoir une certaine quantité d'entropie et d'aléatoire pour être considérée comme sécurisée. C'est pourquoi vous devez vous assurer d'utiliser les bibliothèques cryptographiques appropriées pour générer la clé pour vous.
Vous avez donc vraiment deux implémentations que vous pouvez faire ici, la première consiste à utiliser le code trouvé sur ce thread StackOverflow pour la génération de clés aléatoires . Cette solution utilise un générateur de nombres aléatoires sécurisé pour créer une clé à partir de zéro que vous pouvez utiliser.
L'autre option moins sécurisée consiste à utiliser une entrée utilisateur telle qu'un mot de passe. Le problème dont nous avons discuté est que le mot de passe n'a pas assez d'entropie, nous devrions donc utiliser PBKDF2 , un algorithme qui prend le mot de passe et le renforce. Voici une implémentation StackOverflow qui m'a plu . Cependant, la bibliothèque Google Tink a tout cela intégré et vous devriez en profiter.
Développeurs Android
Un point important à souligner ici est de savoir que votre code Android est rétro-ingénieur et dans la plupart des cas, la plupart du code java l'est aussi. Cela signifie que si vous stockez le mot de passe en texte brut dans votre code. Un hacker peut facilement le récupérer. Habituellement, pour ce type de cryptage, vous souhaitez utiliser la cryptographie asymétrique et ainsi de suite. Cela sort du cadre de cet article, j'éviterai donc de m'y plonger.
Une lecture intéressante de 2013 : souligne que 88% des implémentations de Crypto sous Android ont été mal effectuées.
Dernières pensées
Encore une fois, je suggérerais d'éviter d'implémenter directement la bibliothèque java pour crypto et d'utiliser Google Tink , cela vous évitera des maux de tête car ils ont vraiment fait du bon travail en implémentant correctement tous les algorithmes. Et même dans ce cas, assurez-vous de vérifier les problèmes soulevés sur le github Tink, les vulnérabilités pop-up ici et là.
Si vous avez des questions ou des commentaires, n'hésitez pas à commenter! La sécurité est en constante évolution et vous devez faire de votre mieux pour la suivre :)