Je crée une application qui stockera les mots de passe, que l'utilisateur peut récupérer et voir. Les mots de passe sont pour un périphérique matériel, il est donc hors de question de vérifier les hachages.
Ce que j'ai besoin de savoir, c'est:
Comment crypter et décrypter un mot de passe en PHP?
Quel est l'algorithme le plus sûr pour crypter les mots de passe?
Où stocker la clé privée?
Au lieu de stocker la clé privée, est-ce une bonne idée de demander aux utilisateurs de saisir la clé privée chaque fois qu'ils ont besoin d'un mot de passe déchiffré? (Les utilisateurs de cette application peuvent être dignes de confiance)
De quelles manières le mot de passe peut-il être volé et déchiffré? De quoi ai-je besoin d'être conscient?
php
security
encryption
passwords
HyderA
la source
la source
Réponses:
Personnellement, j'utiliserais
mcrypt
comme d'autres postés. Mais il y a beaucoup plus à noter ...Comment crypter et décrypter un mot de passe en PHP?
Voir ci-dessous pour une classe forte qui s'occupe de tout pour vous:
Quel est l'algorithme le plus sûr pour crypter les mots de passe?
le plus sûr ? n'importe lequel d'entre eux. La méthode la plus sûre si vous allez chiffrer est de vous protéger contre les vulnérabilités de divulgation d'informations (XSS, inclusion à distance, etc.). S'il sort, l'attaquant peut éventuellement déchiffrer le chiffrement (aucun chiffrement n'est 100% irréversible sans la clé - comme le souligne @NullUserException, ce n'est pas tout à fait vrai. Il existe des schémas de chiffrement impossibles à déchiffrer comme OneTimePad ) .
Où stocker la clé privée?
Ce que je ferais, c'est utiliser 3 clés. L'un est fourni par l'utilisateur, l'un est spécifique à l'application et l'autre est spécifique à l'utilisateur (comme un sel). La clé spécifique à l'application peut être stockée n'importe où (dans un fichier de configuration en dehors de la racine Web, dans une variable d'environnement, etc.). Celui spécifique à l'utilisateur serait stocké dans une colonne de la base de données à côté du mot de passe crypté. Celui fourni par l'utilisateur ne serait pas stocké. Ensuite, vous feriez quelque chose comme ceci:
L'avantage ici, c'est que 2 des clés peuvent être compromises sans que les données soient compromises. S'il y a une attaque par injection SQL, ils peuvent obtenir le
$userKey
, mais pas l'autre 2. S'il y a un exploit de serveur local, ils peuvent obtenir$userKey
et$serverKey
, mais pas le troisième$userSuppliedKey
. S'ils battent l'utilisateur avec une clé, ils peuvent obtenir les$userSuppliedKey
2 autres, mais pas les 2 autres (mais encore une fois, si l'utilisateur est battu avec une clé, vous êtes de toute façon trop tard).Au lieu de stocker la clé privée, est-ce une bonne idée de demander aux utilisateurs de saisir la clé privée chaque fois qu'ils ont besoin d'un mot de passe déchiffré? (Les utilisateurs de cette application peuvent être dignes de confiance)
Absolument. En fait, c'est la seule façon dont je le ferais. Sinon, vous devrez stocker une version non chiffrée dans un format de stockage durable (mémoire partagée comme APC ou Memcached, ou dans un fichier de session). Cela vous expose à des compromis supplémentaires. Ne stockez jamais la version non chiffrée du mot de passe dans autre chose qu'une variable locale.
De quelles manières le mot de passe peut-il être volé et déchiffré? De quoi ai-je besoin d'être conscient?
Toute forme de compromission de vos systèmes leur permettra de visualiser les données cryptées. S'ils peuvent injecter du code ou accéder à votre système de fichiers, ils peuvent afficher les données déchiffrées (car ils peuvent éditer les fichiers qui déchiffrent les données). Toute forme d'attaque Replay ou MITM leur donnera également un accès complet aux clés impliquées. Renifler le trafic HTTP brut leur donnera également les clés.
Utilisez SSL pour tout le trafic. Et assurez-vous que rien sur le serveur ne présente de vulnérabilités (CSRF, XSS, injection SQL, escalade de privilèges, exécution de code à distance, etc.).
Edit: Voici une implémentation de classe PHP d'une méthode de cryptage forte:
Notez que je suis en utilisant une fonction ajoutée en PHP 5.6:
hash_equals
. Si vous êtes sur une valeur inférieure à 5,6, vous pouvez utiliser cette fonction de remplacement qui implémente une fonction de comparaison sécurisée en fonction du temps en utilisant la double vérification HMAC :Usage:
Ensuite, pour décrypter:
Notez que j'ai utilisé
$e2
la deuxième fois pour vous montrer que différentes instances déchiffreront toujours correctement les données.Maintenant, comment ça marche / pourquoi l'utiliser sur une autre solution:
Clés
Les clés ne sont pas utilisées directement. Au lieu de cela, la clé est étirée par une dérivation PBKDF2 standard.
La clé utilisée pour le chiffrement est unique pour chaque bloc de texte chiffré. La clé fournie devient donc une "clé principale". Cette classe fournit donc une rotation de clé pour les clés de chiffrement et d'authentification.
REMARQUE IMPORTANTE , le
$rounds
paramètre est configuré pour de vraies clés aléatoires de force suffisante (128 bits de cryptographie aléatoire au minimum). Si vous allez utiliser un mot de passe, ou une clé non aléatoire (ou moins aléatoire que 128 bits de CS aléatoire), vous devez augmenter ce paramètre. Je suggérerais un minimum de 10000 pour les mots de passe (plus vous pouvez vous le permettre, mieux c'est, mais cela ajoutera à l'exécution) ...Intégrité des données
Chiffrement:
MCRYPT_BLOWFISH
ouMCRYPT_RIJNDAEL_128
cyphers etMCRYPT_MODE_CBC
pour le mode. C'est assez fort, et toujours assez rapide (un cycle de cryptage et de décryptage prend environ 1/2 seconde sur ma machine).Maintenant, en ce qui concerne le point 3 de la première liste, ce que cela vous donnerait est une fonction comme celle-ci:
Vous pouvez l'étirer dans la
makeKey()
fonction, mais comme il sera étiré plus tard, il n'y a pas vraiment d'intérêt à le faire.En ce qui concerne la taille de stockage, cela dépend du texte brut. Blowfish utilise une taille de bloc de 8 octets, vous aurez donc:
Donc, pour une source de données à 16 caractères, il y aura 16 caractères de données à chiffrer. Cela signifie donc que la taille réelle des données chiffrées est de 16 octets en raison du remplissage. Ajoutez ensuite les 16 octets pour le sel et 64 octets pour le hmac et la taille totale stockée est de 96 octets. Il y a donc au mieux un overhead de 80 caractères, et au pire un overhead de 87 caractères ...
J'espère que cela aide ...
Remarque: 12/11/12: Je viens de mettre à jour cette classe avec une méthode de cryptage BEAUCOUP meilleure, en utilisant de meilleures clés dérivées et en corrigeant la génération MAC ...
la source
-64
s en-128
aidés (donc vous obtenez$enc = substr($data, 128, -128)
et$mac = substr($data, -128);
Comment crypter et décrypter un mot de passe en PHP? En implémentant l'un des nombreux algorithmes de chiffrement. (ou en utilisant l'une des nombreuses bibliothèques)
Quel est l'algorithme le plus sûr pour crypter les mots de passe? Il existe des tonnes d'algorithmes différents, dont aucun n'est sécurisé à 100%. Mais beaucoup d'entre eux sont suffisamment sécurisés pour le commerce et même à des fins militaires
Où stocker la clé privée? Si vous avez décidé d'implémenter un algorithme de cryptographie à clé publique (par exemple RSA), vous ne stockez pas de clé privée. l'utilisateur a une clé privée. votre système a une clé publique qui peut être stockée où vous le souhaitez.
Au lieu de stocker la clé privée, est-ce une bonne idée de demander aux utilisateurs de saisir la clé privée chaque fois qu'ils ont besoin d'un mot de passe déchiffré? (On peut faire confiance aux utilisateurs de cette application) Eh bien, si votre utilisateur peut se souvenir de nombres premiers ridiculement longs, oui, pourquoi pas. Mais en général, vous devrez mettre au point le système qui permettra à l'utilisateur de stocker sa clé quelque part.
De quelles manières le mot de passe peut-il être volé et déchiffré? De quoi dois-je être conscient? Cela dépend de l'algorithme utilisé. Cependant, assurez-vous toujours que vous n'envoyez pas de mot de passe non chiffré vers ou depuis l'utilisateur. Soit le crypter / le décrypter côté client, soit utiliser https (ou utiliser d'autres moyens cryptographiques pour sécuriser la connexion entre le serveur et le client).
Cependant, si tout ce dont vous avez besoin est de stocker les mots de passe de manière cryptée, je vous suggère d'utiliser un simple chiffrement XOR. Le principal problème de cet algorithme est qu'il pourrait être facilement cassé par une analyse de fréquence. Cependant, comme généralement les mots de passe ne sont pas composés de longs paragraphes de texte anglais, je ne pense pas que vous devriez vous en préoccuper. Le deuxième problème avec XOR Cipher est que si vous avez un message à la fois crypté et décrypté, vous pouvez facilement trouver le mot de passe avec lequel il a été crypté. Encore une fois, ce n'est pas un gros problème dans votre cas car cela n'affecte que l'utilisateur qui a déjà été compromis par d'autres moyens.
la source
L'exemple du manuel est légèrement modifié pour cet exemple):
Vous utiliseriez mcrypt_decrypt pour déchiffrer votre mot de passe.
Le meilleur algorithme est plutôt subjectif - demandez à 5 personnes, obtenez 5 réponses. Personnellement, si la valeur par défaut (Blowfish) ne vous suffit pas, vous avez probablement de plus gros problèmes!
Étant donné qu'il est nécessaire à PHP pour crypter - vous n'êtes pas sûr de pouvoir le cacher n'importe où - bienvenue à ce sujet. Les meilleures pratiques de codage PHP standard s'appliquent bien sûr!
Étant donné que la clé de cryptage sera de toute façon dans votre code, ne savez pas ce que vous allez gagner, à condition que le reste de votre application soit sécurisé.
De toute évidence, si le mot de passe crypté et la clé de cryptage sont volés, la partie est terminée.
Je mettrais un cavalier sur ma réponse - je ne suis pas un expert en crypto PHP, mais, je pense que ce que j'ai répondu est une pratique standard - je suis heureux de faire des commentaires d'autres.
la source
$pass = $text
. Je pense qu'il a changé cela pour répondre à la question, et n'a pas remarqué la deuxième occurrence.MCRYPT_MODE_ECB
n'utilise pas d'IV. Deuxièmement, si c'est le cas, vous devrez stocker l'IV car vous ne pouvez pas décrypter les données sans lui ...De nombreux utilisateurs ont suggéré d'utiliser mcrypt ... ce qui est correct, mais j'aime aller plus loin pour le rendre facilement stocké et transféré (car parfois les valeurs cryptées peuvent les rendre difficiles à envoyer en utilisant d'autres technologies comme curl ou json) .
Après avoir chiffré avec succès à l'aide de mcrypt, exécutez-le via base64_encode, puis convertissez-le en code hexadécimal. Une fois en code hexadécimal, il est facile de transférer de différentes manières.
Et de l'autre côté:
la source
Je ne suggérerais le cryptage à clé publique que si vous souhaitez pouvoir définir le mot de passe d'un utilisateur sans son interaction (cela peut être pratique pour les réinitialisations et les mots de passe partagés).
Clé publique
openssl_public_encrypt
etopenssl_private_decrypt
Symétrique
Tous les deux
4
. Oui - les utilisateurs devraient saisir leur mot de passe d'application à chaque fois, mais le stocker dans la session soulèverait d'autres problèmes5
.la source
openssl_private_decrypt()
.J'ai essayé quelque chose comme ça, mais veuillez noter que je ne suis pas cryptographe ni que je possède une connaissance approfondie de
php
tout langage de programmation. C'est juste une idée. Mon idée est de stockerkey
dans un fichier oudatabase
(ou d'entrer manuellement) qui (emplacement) ne peut pas être facilement prédit (et bien sûr, tout sera déchiffré un jour, le concept est d'allonger le temps de déchiffrement) et de crypter les informations sensibles.Veuillez noter que ce n'est qu'un concept. Toute amélioration de ce code serait très appréciable.
la source
Hein? Je ne comprends pas. Voulez-vous simplement dire que le mot de passe doit être récupérable?
Comme d'autres l'ont dit, l'extension mcrypt donne accès à de nombreuses fonctions cryptographiques - mais vous invitez vos utilisateurs à mettre tous leurs œufs dans le même panier - un qui sera potentiellement une cible pour les attaquants - et si vous ne savez même pas comment commencer à résoudre le problème, alors vous ne rendez pas service à vos utilisateurs. Vous n'êtes pas en mesure de comprendre comment protéger les données.
La plupart des vulnérabilités de sécurité ne sont pas dues au fait que l'algorithme sous-jacent est défectueux ou non sécurisé, mais à des problèmes liés à la façon dont l'algorithme est utilisé dans le code de l'application.
Cela dit, il est possible de construire un système raisonnablement sécurisé.
Vous ne devez envisager le cryptage asymétrique que si vous avez l'obligation pour un utilisateur de créer un message sécurisé lisible par un autre utilisateur (spécifique). La raison étant que son calcul est coûteux. Si vous souhaitez simplement fournir un référentiel permettant aux utilisateurs de saisir et de récupérer leurs propres données, le chiffrement symétrique est adéquat.
Si, cependant, vous stockez la clé pour déchiffrer le message au même endroit que le message chiffré (ou là où le message chiffré est stocké), le système n'est pas sécurisé. Utilisez le même jeton pour authentifier l'utilisateur que pour la clé de déchiffrement (ou dans le cas d'un cryptage asymétrique, utilisez le jeton comme phrase de passe de clé privée). Étant donné que vous devrez stocker le jeton sur le serveur où le décryptage a lieu au moins temporairement, vous pouvez envisager d'utiliser un substrat de stockage de session non interrogeable ou de transmettre le jeton directement à un démon associé à la session qui stockerait le token en mémoire et effectuer le décryptage des messages à la demande.
la source
Utilisez password_hash et password_verify
Et pour décrypter:
la source