Cryptage bidirectionnel: j'ai besoin de stocker des mots de passe qui peuvent être récupérés

174

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:

  1. Comment crypter et décrypter un mot de passe en PHP?

  2. Quel est l'algorithme le plus sûr pour crypter les mots de passe?

  3. Où stocker la clé privée?

  4. 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)

  5. De quelles manières le mot de passe peut-il être volé et déchiffré? De quoi ai-je besoin d'être conscient?

HyderA
la source
1
Remarque: Libsodium est maintenant compilé dans le noyau PHP pour> = 7.2. Ce serait la solution «aller» maintenant car il est plein de méthodes modernes contrairement à mcrypt qui est considéré comme obsolète et a été supprimé.
Exhibitioner

Réponses:

212

Personnellement, j'utiliserais mcryptcomme d'autres postés. Mais il y a beaucoup plus à noter ...

  1. 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:

  2. 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 ) .

  3. 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:

    $key = $userKey . $serverKey . $userSuppliedKey;

    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 $userKeyet $serverKey, mais pas le troisième $userSuppliedKey. S'ils battent l'utilisateur avec une clé, ils peuvent obtenir les $userSuppliedKey2 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).

  4. 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.

  5. 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:

/**
 * A class to handle secure encryption and decryption of arbitrary data
 *
 * Note that this is not just straight encryption.  It also has a few other
 *  features in it to make the encrypted data far more secure.  Note that any
 *  other implementations used to decrypt data will have to do the same exact
 *  operations.  
 *
 * Security Benefits:
 *
 * - Uses Key stretching
 * - Hides the Initialization Vector
 * - Does HMAC verification of source data
 *
 */
class Encryption {

    /**
     * @var string $cipher The mcrypt cipher to use for this instance
     */
    protected $cipher = '';

    /**
     * @var int $mode The mcrypt cipher mode to use
     */
    protected $mode = '';

    /**
     * @var int $rounds The number of rounds to feed into PBKDF2 for key generation
     */
    protected $rounds = 100;

    /**
     * Constructor!
     *
     * @param string $cipher The MCRYPT_* cypher to use for this instance
     * @param int    $mode   The MCRYPT_MODE_* mode to use for this instance
     * @param int    $rounds The number of PBKDF2 rounds to do on the key
     */
    public function __construct($cipher, $mode, $rounds = 100) {
        $this->cipher = $cipher;
        $this->mode = $mode;
        $this->rounds = (int) $rounds;
    }

    /**
     * Decrypt the data with the provided key
     *
     * @param string $data The encrypted datat to decrypt
     * @param string $key  The key to use for decryption
     * 
     * @returns string|false The returned string if decryption is successful
     *                           false if it is not
     */
    public function decrypt($data, $key) {
        $salt = substr($data, 0, 128);
        $enc = substr($data, 128, -64);
        $mac = substr($data, -64);

        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        if (!hash_equals(hash_hmac('sha512', $enc, $macKey, true), $mac)) {
             return false;
        }

        $dec = mcrypt_decrypt($this->cipher, $cipherKey, $enc, $this->mode, $iv);

        $data = $this->unpad($dec);

        return $data;
    }

    /**
     * Encrypt the supplied data using the supplied key
     * 
     * @param string $data The data to encrypt
     * @param string $key  The key to encrypt with
     *
     * @returns string The encrypted data
     */
    public function encrypt($data, $key) {
        $salt = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
        list ($cipherKey, $macKey, $iv) = $this->getKeys($salt, $key);

        $data = $this->pad($data);

        $enc = mcrypt_encrypt($this->cipher, $cipherKey, $data, $this->mode, $iv);

        $mac = hash_hmac('sha512', $enc, $macKey, true);
        return $salt . $enc . $mac;
    }

    /**
     * Generates a set of keys given a random salt and a master key
     *
     * @param string $salt A random string to change the keys each encryption
     * @param string $key  The supplied key to encrypt with
     *
     * @returns array An array of keys (a cipher key, a mac key, and a IV)
     */
    protected function getKeys($salt, $key) {
        $ivSize = mcrypt_get_iv_size($this->cipher, $this->mode);
        $keySize = mcrypt_get_key_size($this->cipher, $this->mode);
        $length = 2 * $keySize + $ivSize;

        $key = $this->pbkdf2('sha512', $key, $salt, $this->rounds, $length);

        $cipherKey = substr($key, 0, $keySize);
        $macKey = substr($key, $keySize, $keySize);
        $iv = substr($key, 2 * $keySize);
        return array($cipherKey, $macKey, $iv);
    }

    /**
     * Stretch the key using the PBKDF2 algorithm
     *
     * @see http://en.wikipedia.org/wiki/PBKDF2
     *
     * @param string $algo   The algorithm to use
     * @param string $key    The key to stretch
     * @param string $salt   A random salt
     * @param int    $rounds The number of rounds to derive
     * @param int    $length The length of the output key
     *
     * @returns string The derived key.
     */
    protected function pbkdf2($algo, $key, $salt, $rounds, $length) {
        $size   = strlen(hash($algo, '', true));
        $len    = ceil($length / $size);
        $result = '';
        for ($i = 1; $i <= $len; $i++) {
            $tmp = hash_hmac($algo, $salt . pack('N', $i), $key, true);
            $res = $tmp;
            for ($j = 1; $j < $rounds; $j++) {
                 $tmp  = hash_hmac($algo, $tmp, $key, true);
                 $res ^= $tmp;
            }
            $result .= $res;
        }
        return substr($result, 0, $length);
    }

    protected function pad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $padAmount = $length - strlen($data) % $length;
        if ($padAmount == 0) {
            $padAmount = $length;
        }
        return $data . str_repeat(chr($padAmount), $padAmount);
    }

    protected function unpad($data) {
        $length = mcrypt_get_block_size($this->cipher, $this->mode);
        $last = ord($data[strlen($data) - 1]);
        if ($last > $length) return false;
        if (substr($data, -1 * $last) !== str_repeat(chr($last), $last)) {
            return false;
        }
        return substr($data, 0, -1 * $last);
    }
}

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 :

function hash_equals($a, $b) {
    $key = mcrypt_create_iv(128, MCRYPT_DEV_URANDOM);
    return hash_hmac('sha512', $a, $key) === hash_hmac('sha512', $b, $key);
}

Usage:

$e = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$encryptedData = $e->encrypt($data, $key);

Ensuite, pour décrypter:

$e2 = new Encryption(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
$data = $e2->decrypt($encryptedData, $key);

Notez que j'ai utilisé $e2la 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:

  1. 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 $roundsparamè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) ...

  2. Intégrité des données

    • La version mise à jour utilise ENCRYPT-THEN-MAC, qui est une méthode bien meilleure pour garantir l'authenticité des données cryptées.
  3. Chiffrement:

    • Il utilise mcrypt pour effectuer le cryptage. Je suggérerais d'utiliser soit MCRYPT_BLOWFISHou MCRYPT_RIJNDAEL_128cyphers et MCRYPT_MODE_CBCpour 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:

function makeKey($userKey, $serverKey, $userSuppliedKey) {
    $key = hash_hmac('sha512', $userKey, $serverKey);
    $key = hash_hmac('sha512', $key, $userSuppliedKey);
    return $key;
}

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:

  • 16 octets pour le sel
  • 64 octets pour le hmac
  • longueur des données
  • Remplissage pour que la longueur des données% 8 == 0

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 ...

ircmaxell
la source
3
Quelqu'un ne comprend pas ce que cela signifie «pause». @IRC beau travail sur la classe, c'est un très bon code.
jcolebrand
1
Ce qui suit renvoie false. Une idée pourquoi? $ x = nouveau cryptage (MCRYPT_BlOWFISH, MCRYPT_MODE_CBC); $ test = $ x-> encrypt ("test", "a"); echo var_dump ($ x-> decrypt ($ test, "a"));
The Wavelength
2
Oh et encore dans la fonction de déchiffrement en changeant les deux -64s en -128aidés (donc vous obtenez $enc = substr($data, 128, -128)et$mac = substr($data, -128);
cosmorogers
4
@ircmaxell Cela fait un bon bout de temps depuis la dernière révision du code, donc je me demande s'il est à jour. J'ai besoin d'utiliser quelque chose de similaire pour une application financière et ce serait bien si vous
donniez
2
Avertissement! L'extension mcrypt a été abandonnée depuis près d'une décennie maintenant, et était également assez complexe à utiliser. Il a donc été abandonné au profit d'OpenSSL, où il sera supprimé du noyau et dans PECL en PHP 7.2. th1.php.net/manual/en/migration71.deprecated.php
vee
15

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.

Ivan
la source
À la réponse 3, lorsque vous dites que les utilisateurs ont une clé privée, je ne comprends pas ce que cela signifie. Vous ne recommandez pas de transmettre manuellement les clés privées à l'application par l'utilisateur, alors comment les clés privées sont-elles transmises à l'application?
HyderA
Eh bien, c'est un peu un problème. La clé privée peut être stockée dans le fichier texte, puis copiée dans l'application. La clé peut également être stockée sur le serveur, mais dans ce cas, elle doit toujours être cryptée avec un autre algorithme de cryptage comme XOR. L'utilisation de XOR ici dans ce cas est suffisamment sécurisée car il n'y a qu'une seule paire mot de passe-message et le message est assez aléatoire, donc l'analyse de fréquence ne doit pas être utilisée.
Ivan
4
Je ne recommanderais certainement pas d'implémenter vous-même un algorithme de cryptage, il y a trop de pièges potentiels et les bibliothèques existantes ont été testées et analysées par de nombreuses personnes.
Long Ears
Le principal problème avec XOR est que si quelqu'un vole les données de votre application et ne connaît qu'un seul des mots de passe d'un utilisateur, il peut déchiffrer tous les autres mots de passe de cet utilisateur.
Long Ears
1
@Ivan: oui, mais c'est l'un des cas où je pense que le bricolage est vraiment vraiment mauvais à moins que vous ne compreniez VRAIMENT la cryptographie. Il existe des chiffrements forts, pourquoi ne pas les utiliser?
ircmaxell
13
  1. La fonction PHP que vous recherchez est Mcrypt ( http://www.php.net/manual/en/intro.mcrypt.php ).

L'exemple du manuel est légèrement modifié pour cet exemple):

<?php
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "This is a very secret key";
$pass = "PasswordHere";
echo strlen($pass) . "\n";

$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $pass, MCRYPT_MODE_ECB, $iv);
echo strlen($crypttext) . "\n";
?>

Vous utiliseriez mcrypt_decrypt pour déchiffrer votre mot de passe.

  1. 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!

  2. É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!

  3. É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é.

  4. 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.

Jon Rhoades
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.
HyderA
3
Deux choses à noter. Premièrement, MCRYPT_MODE_ECBn'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 ...
ircmaxell
"Le meilleur algorithme est plutôt subjectif - demandez à 5 personnes, obtenez 5 réponses. Personnellement, si la valeur par défaut (Blowfish) n'est pas assez bonne pour vous, vous avez probablement de plus gros problèmes!" C'est totalement faux. Tout expert en crypto sera plus ou moins d'accord avec gist.github.com/tqbf/be58d2d39690c3b366ad qui exclut spécifiquement blowfish
Scott Arciszewski
6

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.

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $unencrypted);
$encrypted = $ua."||||".$iv;
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$encrypted = base64_encode($encrypted);
$encrypted = array_shift(unpack('H*', $encrypted));

Et de l'autre côté:

$encrypted = pack('H*', $encrypted);
$encrypted = base64_decode($encrypted);
list($encrypted,$iv) = explode("||||",$encrypted,2);
$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$key = substr("SUPERSECRETKEY",0,mcrypt_enc_get_key_size($td));
mcrypt_generic_init($td, $key, $iv);
$unencrypted = mdecrypt_generic($td, $encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
Bradley
la source
2
Eh bien - c'était en 2011: P
Bradley
5

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

  1. L' extension OpenSSL , en particulier openssl_public_encryptetopenssl_private_decrypt
  2. Ce serait un RSA direct en supposant que vos mots de passe correspondent à la taille de la clé - remplissage, sinon vous avez besoin d'une couche symétrique
  3. Stockez les deux clés pour chaque utilisateur, la phrase de passe de la clé privée est le mot de passe de leur application

Symétrique

  1. L' extension Mcrypt
  2. AES-256 est probablement une valeur sûre, mais cela pourrait être une question SO en soi
  3. Vous n'avez pas - ce serait leur mot de passe d'application

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èmes

5.

  • Si quelqu'un vole les données de l'application, elles sont aussi sécurisées que le chiffrement symétrique (pour le schéma de clé publique, il est utilisé pour protéger la clé privée avec la phrase de passe.)
  • Votre application doit certainement être accessible uniquement via SSL, de préférence à l'aide de certificats clients.
  • Pensez à ajouter un deuxième facteur d'authentification qui ne serait utilisé qu'une fois par session, comme un jeton envoyé par SMS.
Longues oreilles
la source
Évitez mcrypt, soyez prudent avec openssl_private_decrypt().
Scott Arciszewski
2

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 phptout langage de programmation. C'est juste une idée. Mon idée est de stocker keydans un fichier ou database(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.

$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH , MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$key = "evenifyouaccessmydatabaseyouwillneverfindmyemail";
$text = "[email protected]";
echo "Key : ".$key."<br/>";
echo "Text : ".$text . "<br/>";
echo "Md5 : ".md5($text). "<br/>";
echo "Sha1 : ".sha1($text). "<br/>";



$crypttext = mcrypt_encrypt(MCRYPT_BLOWFISH , $key, $text, MCRYPT_MODE_ECB, $iv);
echo "Crypted Data : ".$crypttext."<br>";

$base64 = base64_encode($crypttext);
echo "Encoded Data : ".$base64."<br/>";
$decode =  base64_decode($base64);


$decryptdata = mcrypt_decrypt(MCRYPT_BLOWFISH , $key, $crypttext, MCRYPT_MODE_ECB, $iv);

echo "Decoded Data : ".ereg_replace("?", null ,  $decryptdata); 
//event if i add '?' to the sting to the text it works, I don't know why.

Veuillez noter que ce n'est qu'un concept. Toute amélioration de ce code serait très appréciable.

Santosh Linkha
la source
2

Les mots de passe sont pour un périphérique matériel, il est donc hors de question de vérifier les hachages

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.

symcbean
la source
1

Utilisez password_hash et password_verify

<?php
/**
 * In this case, we want to increase the default cost for BCRYPT to 12.
 * Note that we also switched to BCRYPT, which will always be 60 characters.
 */
$options = [
    'cost' => 12,
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>

Et pour décrypter:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}
?>
jvitoroc
la source