Ce dont j'ai besoin est de crypter la chaîne qui apparaîtra dans le code à barres 2D (PDF-417) afin que lorsque quelqu'un a une idée de scanner, rien ne sera lisible.
Autres exigences:
- ne devrait pas être compliqué
- il ne doit pas être constitué de RSA, d'infrastructure PKI, de paires de clés, etc.
Cela doit être assez simple pour se débarrasser des gens qui fouinent et facile à déchiffrer pour les autres entreprises intéressées à obtenir ces données. Ils nous appellent, nous leur disons la norme ou leur donnons une clé simple qui peut ensuite être utilisée pour le décryptage.
Ces entreprises pourraient probablement utiliser des technologies différentes, il serait donc bon de s'en tenir à une norme qui n'est pas liée à une plate-forme ou une technologie particulière.
Que suggérez-vous? Y a-t-il une classe Java qui fait encrypt()
et decrypt()
sans trop de complications pour atteindre des normes de sécurité élevées?
la source
Réponses:
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:
... 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
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.
Mise en œuvre de CBC
Si vous choisissez d'implémenter le mode CBC, faites-le avec PKCS7Padding comme suit:
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.
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 :)
la source
getInstanceStrong()
méthode deCipher
est préférable à SHA1PRNGJe recommanderais d'utiliser un chiffrement symétrique standard largement disponible comme DES , 3DES ou AES . Bien que ce ne soit pas l'algorithme le plus sûr, il existe de nombreuses implémentations et il vous suffit de donner la clé à quiconque est censé déchiffrer les informations du code-barres. javax.crypto.Cipher est ce avec quoi vous voulez travailler ici.
Supposons que les octets à crypter soient
Ensuite, vous aurez besoin de la clé et des octets du vecteur d'initialisation
Vous pouvez maintenant initialiser le chiffrement pour l'algorithme que vous sélectionnez:
Le cryptage se déroulerait comme ceci:
Et un décryptage comme celui-ci:
la source
DESede
algorithme? Puisqu'il s'agit d'une question (et d'une réponse) populaire, il serait dommage d'encourager les gens à utiliser DES, car le chiffrement est si faible par rapport aux normes actuelles.J'utilise le Base64Encoder / Decoder de Sun qui se trouve dans le JRE de Sun, pour éviter encore un autre JAR dans la lib. C'est dangereux du point de vue de l'utilisation d'OpenJDK ou du JRE d'un autre. En plus de cela, y a-t-il une autre raison pour laquelle je devrais envisager d'utiliser Apache commons lib avec Encoder / Decoder?
la source
merci ive a fait cette classe en utilisant votre code peut-être que quelqu'un la trouve utilisateur
crypteur d'objets
la source
Mise à jour le 12-DEC-2019
Contrairement à certains autres modes comme CBC, le mode GCM ne nécessite pas que l'IV soit imprévisible. La seule exigence est que l'IV doit être unique pour chaque invocation avec une clé donnée. S'il se répète une fois pour une clé donnée, la sécurité peut être compromise. Un moyen simple d'y parvenir est d'utiliser un IV aléatoire à partir d'un puissant générateur de nombres pseudo aléatoires comme indiqué ci-dessous.
L'utilisation d'une séquence ou d'un horodatage comme IV est également possible, mais ce n'est peut-être pas aussi trivial que cela puisse paraître. Par exemple, si le système ne conserve pas correctement la trace des séquences déjà utilisées comme IV dans une mémoire persistante, un appel peut répéter un IV après un redémarrage du système. De même, il n'y a pas d'horloge parfaite. Réajuster l'horloge de l'ordinateur, etc.
De plus, la clé doit être tournée tous les 2 ^ 32 appels. Pour plus de détails sur l'exigence IV, reportez-vous à cette réponse et aux recommandations du NIST .
C'est le code de cryptage et de décryptage que je viens d'écrire dans Java 8 en tenant compte des points suivants. J'espère que quelqu'un trouvera cela utile:
Algorithme de chiffrement : le chiffrement par bloc AES avec une clé de 256 bits est considéré comme suffisamment sécurisé. Pour crypter un message complet, un mode doit être sélectionné. Un cryptage authentifié (qui assure à la fois confidentialité et intégrité) est recommandé. GCM, CCM et EAX sont les modes de cryptage authentifiés les plus couramment utilisés. GCM est généralement préféré et il fonctionne bien dans les architectures Intel qui fournissent des instructions dédiées pour GCM. Ces trois modes sont des modes basés sur le CTR (basés sur le compteur) et n'ont donc pas besoin de remplissage. En conséquence, ils ne sont pas vulnérables aux attaques liées au rembourrage
Un vecteur d'initialisation (IV) est requis pour GCM. La IV n'est pas un secret. La seule exigence étant qu'elle doit être aléatoire ou imprévisible. En Java, la
SecuredRandom
classe est destinée à produire des nombres pseudo-aléatoires cryptographiquement forts. L'algorithme de génération de nombres pseudo-aléatoires peut être spécifié dans lagetInstance()
méthode. Cependant, depuis Java 8, la méthode recommandée est d'utiliser lagetInstanceStrong()
méthode qui utilisera l'algorithme le plus puissant configuré et fourni par leProvider
Le NIST recommande 96 bits IV pour GCM afin de promouvoir l'interopérabilité, l'efficacité et la simplicité de conception
Pour assurer une sécurité supplémentaire, dans l'implémentation suivante
SecureRandom
est réamorcé après la production tous les 2 ^ 16 octets de génération d'octets pseudo aléatoiresLe destinataire doit connaître l'IV pour pouvoir décrypter le texte chiffré. Par conséquent, l'IV doit être transféré avec le texte chiffré. Certaines implémentations envoient le IV comme AD (Associated Data), ce qui signifie que l'étiquette d'authentification sera calculée à la fois sur le texte chiffré et sur l'IV. Cependant, ce n'est pas obligatoire. Le IV peut être simplement pré-suspendu avec le texte chiffré car si l'IV est changé pendant la transmission en raison d'une attaque délibérée ou d'une erreur de réseau / système de fichiers, la validation de la balise d'authentification échouera de toute façon.
Les chaînes ne doivent pas être utilisées pour contenir le message en texte clair ou la clé car les chaînes sont immuables et nous ne pouvons donc pas les effacer après utilisation. Ces chaînes non effacées persistent ensuite dans la mémoire et peuvent apparaître dans un vidage de tas. Pour la même raison, le client appelant ces méthodes de cryptage ou de décryptage doit effacer toutes les variables ou tableaux contenant le message ou la clé une fois qu'ils ne sont plus nécessaires.
Aucun fournisseur n'est codé en dur dans le code suivant les recommandations générales
Enfin, pour la transmission sur le réseau ou le stockage, la clé ou le texte chiffré doit être codé en utilisant le codage Base64. Les détails de Base64 peuvent être trouvés ici . L'approche Java 8 doit être suivie
Les tableaux d'octets peuvent être effacés en utilisant:
Cependant, à partir de Java 8, il n'y a pas de moyen simple de clarifier
SecretKeyspec
etSecretKey
comme les implémentations de ces deux interfaces ne semblent pas avoir implémenté la méthodedestroy()
de l'interfaceDestroyable
. Dans le code suivant, une méthode distincte est écrite pour effacerSecretKeySpec
etSecretKey
utiliser la réflexion.La clé doit être générée en utilisant l'une des deux approches mentionnées ci-dessous.
Notez que les clés sont des secrets comme les mots de passe, mais contrairement aux mots de passe destinés à un usage humain, les clés sont destinées à être utilisées par des algorithmes cryptographiques et doivent donc être générées en utilisant uniquement la méthode ci-dessus.
La clé de chiffrement peut être générée principalement de deux manières:
Sans aucun mot de passe
Avec mot de passe
Mise à jour basée sur les commentaires
Comme l'a souligné @MaartenBodewes, ma réponse n'en a pas traité
String
comme l'exige la question. Par conséquent, je vais essayer de combler cette lacune au cas où quelqu'un trébucherait sur cette réponse et s'interrogerait sur la manipulationString
.Comme indiqué précédemment dans la réponse, la gestion des informations sensibles dans a
String
n'est, en général, pas une bonne idée car elleString
est immuable et donc nous ne pouvons pas l'effacer après utilisation. Et comme nous le savons, même si aString
n'a pas de référence forte, le garbage collector ne se précipite pas immédiatement pour le supprimer du tas. Ainsi, leString
continue à être présent dans la mémoire pendant une fenêtre de temps inconnue même s'il n'est pas accessible au programme. Le problème avec cela est qu'un vidage de tas pendant cette période révélerait les informations sensibles. Par conséquent, il est toujours préférable de gérer toutes les informations sensibles dans un tableau d'octets ou un tableau de caractères, puis de remplir le tableau avec des 0 une fois leur objectif atteint.Cependant, avec toutes ces connaissances, si nous nous retrouvons toujours dans une situation où les informations sensibles à chiffrer sont dans a
String
, nous devons d'abord les convertir en un tableau d'octets et invoquer les fonctionsencrypt
etdecrypt
présentées ci-dessus. (L'autre clé d'entrée peut être générée à l'aide de l'extrait de code fourni ci-dessus).A
String
peut être converti en octets de la manière suivante:À partir de Java 8,
String
est stocké en interne dans le tas avecUTF-16
encodage. Cependant, nous l'avons utiliséUTF-8
ici car il prend généralement moins d'espace queUTF-16
, en particulier pour les caractères ASCII.De même, le tableau d'octets chiffré peut également être converti en une chaîne comme ci-dessous:
la source
String
utilisant les fonctions créées ci-dessus serait trivial. Cependant, après avoir lu votre commentaire, je comprends que ce n'est peut-être pas évident. Je vais sûrement modifier pour ajouter ces détails.Que dis-tu de ça:
Fonctionne bien pour moi et est plutôt compact.
la source
input.length <= secret.length
tient et nosecret
n'est jamais réutilisé, cela est sécurisé et appelé aone-time-pad
. Dans ce cas,input.length > secret.length
il s'agit d'une variante du chiffre de Vigenère et considérée comme très faible.Vous pouvez utiliser Jasypt
Avec Jasypt, crypter et vérifier un mot de passe peut être aussi simple que ...
Chiffrement:
Décryptage:
Gradle:
Fonctionnalités:
la source
Jasypt
fournit-elle? Je ne peux pas le comprendre sur leur site Web. Est-il impossible de le distinguer sous les attaques en clair choisi? Intégrité? Confidentialité?Voici mon implémentation de meta64.com en tant que Spring Singleton. Si vous voulez créer une instance de ciper pour chaque appel qui fonctionnerait également, vous pouvez supprimer les appels «synchronisés», mais attention «cipher» n'est pas thread-safe.
la source
Voici une solution simple avec uniquement
java.*
etjavax.crypto.*
dépendances pour le cryptage des octets assurant confidentialité et intégrité . Il ne doit pas être distingué sous une attaque de texte en clair choisie pour les messages courts de l'ordre de kilo-octets.Il utilise
AES
dans leGCM
mode sans remplissage, une clé de 128 bits est dérivéePBKDF2
avec de nombreuses itérations et un sel statique du mot de passe fourni. Cela garantit que le forçage brutal des mots de passe est difficile et distribue l'entropie sur toute la clé.Un vecteur d'initialisation aléatoire (IV) est généré et sera ajouté au texte chiffré. De plus, l'octet statique
0x01
est ajouté comme premier octet en tant que «version».Le message entier entre dans le code d'authentification de message (MAC) généré par
AES/GCM
.Voilà, aucune classe de chiffrement de dépendances externes assurant la confidentialité et l' intégrité :
Voici l'ensemble du projet avec une belle CLI: https://github.com/trichner/tcrypt
Edit: maintenant avec approprié
encryptString
etdecryptString
la source
encryptString
etdecryptString
:)J'envisagerais d'utiliser quelque chose comme https://www.bouncycastle.org/ C'est une bibliothèque prédéfinie qui vous permet de crypter ce que vous voulez avec un certain nombre de chiffrements différents, je comprends que vous voulez seulement vous protéger contre l'espionnage, mais si vous vraiment veulent protéger les informations, l'utilisation de Base64 ne vous protégera pas réellement.
la source
Voici quelques liens vous permettant de lire ce que Java prend en charge
Crypter / décrypter un flux de données.
JCERefGuide
Exemples de chiffrement Java
la source
Comme beaucoup de gars l'ont déjà dit, vous devriez utiliser un chiffrement standard qui est trop utilisé comme DES ou AES.
Un exemple simple de la façon dont vous pouvez crypter et décrypter une chaîne en java à l'aide d' AES .
la source
Voici une solution de copier / coller. Je recommande également de lire et de voter pour la réponse de @ Konstantino même si elle ne fournit aucun code. Le vecteur d'initialisation (IV) est comme un sel - il ne doit pas être gardé secret. Je suis nouveau sur GCM et apparemment AAD est facultatif et n'est utilisé que dans certaines circonstances. Définissez la clé dans la variable d'environnement
SECRET_KEY_BASE
. Utilisez quelque chose comme KeePass pour générer un mot de passe de 32 caractères. Cette solution est calquée sur ma solution Ruby.Voici un exemple:
la source
Vous voudrez peut-être envisager un outil automatisé pour faire la génération de code de cryptage / décryptage, par exemple. https://www.stringencrypt.com/java-encryption/
Il peut générer différents codes de cryptage et de décryptage à chaque fois pour le cryptage de la chaîne ou du fichier.
C'est assez pratique pour le cryptage rapide des chaînes sans utiliser RSA, AES, etc.
Exemples de résultats:
Nous l'utilisons tout le temps dans notre entreprise.
la source
la source
la source