Comment chiffrer / déchiffrer des données en php?

Je suis actuellement étudiant et j'étudie PHP, j'essaie de faire un simple chiffrement / décryptage de données en PHP. J'ai fait des recherches en ligne et certaines d'entre elles étaient assez confuses(du moins pour moi).

Voici ce que j'essaie de faire:

J'ai une table composée de ces champs (UserID,Fname,Lname,e-Mail,Mot de passe)

Ce que je veux avoir, c'est que tous les champs soient cryptés puis décryptés (est-il possible d'utiliser sha256 pour le cryptage / décryptage, sinon tout algorithme de chiffrement)

Une autre chose que je veux apprendre est comment créer un sens unique hash(sha256) combiné avec un bon "sel". (Fondamentalement, je veux juste avoir une implémentation simple de cryptage / décryptage, hash(sha256)+salt) Monsieur / Madame, vos réponses seraient d'une grande aide et très appréciées. Merci++

100
demandé sur Scott Arciszewski 2012-06-06 18:28:52

6 réponses

Avant-propos

En commençant par votre définition de table:

- UserID
- Fname
- Lname
- Email
- Password
- IV

Voici les changements:

  1. Les champs Fname, Lname et Email seront cryptées à l'aide d'un chiffrement symétrique, fournis par OpenSSL,
  2. le champ IV stocke le vecteur d'initialisation utilisé pour le chiffrement. Les exigences de stockage dépendent du chiffrement et du mode utilisé; plus à ce sujet plus tard.
  3. le champ Password sera haché à l'aide d'un unidirectionnel hachage de mot de passe,

Chiffrement

Chiffrement et le mode

Choisir le meilleur chiffrement et mode de chiffrement dépasse la portée de cette réponse, mais le choix final affecte la taille de la clé de chiffrement et du vecteur d'initialisation; pour ce post, nous utiliserons AES-256-CBC qui a une taille de bloc fixe de 16 octets et une taille de clé de 16, 24 ou 32 octets.

La clé de Chiffrement

Une bonne clé de chiffrement est un blob binaire c'est généré à partir d'un générateur de nombres aléatoires fiable. L'exemple suivant serait recommandé (>=5.3):

$key_size = 32; // 256 bits
$encryption_key = openssl_random_pseudo_bytes($key_size, $strong);
// $strong will be true if the key is crypto safe

Cela peut être fait une ou plusieurs fois (si vous souhaitez créer une chaîne de clés de chiffrement). Gardez-les aussi privées que possible.

IV

Le Vecteur d'initialisation ajoute du caractère aléatoire au chiffrement et est requis pour le mode CBC. Ces valeurs devraient idéalement être utilisées une seule fois (techniquement une fois par clé de chiffrement), donc une mise à jour de n'importe quelle partie d'une rangée devrait le régénérer.

Une fonction est fournie pour vous aider à générer L'IV:

$iv_size = 16; // 128 bits
$iv = openssl_random_pseudo_bytes($iv_size, $strong);

Exemple

Chiffrons le champ name, En utilisant les premiers $encryption_key et $iv; pour ce faire, nous devons pad nos données à la taille du bloc:

function pkcs7_pad($data, $size)
{
    $length = $size - strlen($data) % $size;
    return $data . str_repeat(chr($length), $length);
}

$name = 'Jack';
$enc_name = openssl_encrypt(
    pkcs7_pad($name, 16), // padded data
    'AES-256-CBC',        // cipher and mode
    $encryption_key,      // secret key
    0,                    // options (not used)
    $iv                   // initialisation vector
);

Exigences de stockage

La sortie cryptée, comme L'IV, est binaire; le stockage de ces valeurs dans une base de données peut être effectué en utilisant des types de colonnes désignés tels que BINARY ou VARBINARY.

La sortie la valeur, comme IV, est binaire; pour stocker ces valeurs dans MySQL, envisagez d'utiliser BINARY ou VARBINARY colonnes. Si ce n'est pas une option, vous pouvez également convertir les données binaires dans une représentation textuelle à l'aide de base64_encode() ou bin2hex(), cela nécessite entre 33% à 100% plus d'espace de stockage.

Décryptage

Le déchiffrement des valeurs stockées est similaire:

function pkcs7_unpad($data)
{
    return substr($data, 0, -ord($data[strlen($data) - 1]));
}

$row = $result->fetch(PDO::FETCH_ASSOC); // read from database result
// $enc_name = base64_decode($row['Name']);
// $enc_name = hex2bin($row['Name']);
$enc_name = $row['Name'];
// $iv = base64_decode($row['IV']);
// $iv = hex2bin($row['IV']);
$iv = $row['IV'];

$name = pkcs7_unpad(openssl_decrypt(
    $enc_name,
    'AES-256-CBC',
    $encryption_key,
    0,
    $iv
));

Chiffrement Authentifié

, Vous pouvez encore améliorer l'intégrité de la texte chiffré généré en ajoutant une signature générée à partir d'une clé secrète (différente de la clé de chiffrement) et du texte chiffré. Avant que le texte chiffré ne soit déchiffré, la signature est d'abord vérifiée (de préférence avec une méthode de comparaison à temps constant).

Exemple

// generate once, keep safe
$auth_key = openssl_random_pseudo_bytes(32, $strong);

// authentication
$auth = hash_hmac('sha256', $enc_name, $auth_key, true);
$auth_enc_name = $auth . $enc_name;

// verification
$auth = substr($auth_enc_name, 0, 32);
$enc_name = substr($auth_enc_name, 32);
$actual_auth = hash_hmac('sha256', $enc_name, $auth_key, true);

if (hash_equals($auth, $actual_auth)) {
    // perform decryption
}

Voir aussi: hash_equals()

Hachage

Le Stockage d'un mot de passe réversible dans votre base de données doit être évité autant que possible; vous souhaitez uniquement Vérifier le mot de passe plutôt que connaître son contenu. Si un utilisateur perd son mot de passe, il est préférable de lui permettre de le réinitialiser plutôt que de lui envoyer son mot de passe original (assurez-vous que la réinitialisation du mot de passe ne peut être effectuée que pour un temps limité).

L'application d'une fonction de hachage est une opération à Sens Unique; par la suite, elle peut être utilisée en toute sécurité pour la vérification sans révéler les données d'origine; pour les mots de passe, une méthode de force brute est une approche réalisable pour le découvrir en raison de sa longueur relativement courte et de ses mauvais choix gens.

Des algorithmes de hachage tels que MD5 ou SHA1 ont été créés pour vérifier le contenu du fichier par rapport à une valeur de hachage connue. Ils sont grandement optimisés pour rendre cette vérification aussi rapide que possible tout en étant précis. Compte tenu de leur espace de sortie relativement limité, il était facile de construire une base de données avec des mots de passe connus et leurs sorties de hachage respectives, les tables arc-en-ciel.

Ajouter un sel au mot de passe avant de le hacher rendrait une table arc-en-ciel inutile, mais du matériel récent les progrès ont fait des recherches de force brute une approche viable. C'est pourquoi vous avez besoin d'un algorithme de hachage délibérément lent et tout simplement impossible à optimiser. Il devrait également être en mesure d'augmenter la charge pour le matériel plus rapide sans affecter la capacité de vérifier les hachages de mot de passe existants pour le rendre à l'épreuve du futur.

Actuellement, il y a deux choix populaires disponibles:

  1. PBKDF2 (fonction de dérivation de clé basée sur un mot de passe v2)
  2. bcrypt (alias Blowfish)

Cette réponse utilisera un exemple avec bcrypt.

Génération

Un hachage de mot de passe peut être généré comme ceci:

$password = 'my password';
$random = openssl_random_pseudo_bytes(18);
$salt = sprintf('$2y$%02d$%s',
    13, // 2^n cost factor
    substr(strtr(base64_encode($random), '+', '.'), 0, 22)
);

$hash = crypt($password, $salt);

, Le sel est généré avec openssl_random_pseudo_bytes() pour former un hasard tas de données qui est ensuite exécuté par le biais de base64_encode() et strtr() pour correspondre à la nécessaire alphabet [A-Za-z0-9/.].

Le crypt() fonction de hachage basée sur l'algorithme de ($2y$ pour Blowfish), le facteur de coût (un facteur de 13 prend environ 0.40 s sur une machine 3GHz) et le sel de 22 caractères.

Validation

Une fois que vous avez récupéré la ligne contenant les informations utilisateur, vous validez le mot de passe de cette manière:

$given_password = $_POST['password']; // the submitted password
$db_hash = $row['Password']; // field with the password hash

$given_hash = crypt($given_password, $db_hash);

if (isEqual($given_hash, $db_hash)) {
    // user password verified
}

// constant time string compare
function isEqual($str1, $str2)
{
    $n1 = strlen($str1);
    if (strlen($str2) != $n1) {
        return false;
    }
    for ($i = 0, $diff = 0; $i != $n1; ++$i) {
        $diff |= ord($str1[$i]) ^ ord($str2[$i]);
    }
    return !$diff;
}

Pour vérifier un mot de passe, vous appelez à nouveau crypt() mais vous passez le hachage précédemment calculé comme valeur de sel. La valeur de retour donne le même hachage si le mot de passe donné correspond au hachage. Pour vérifier le hachage, il est souvent recommandé d'utiliser un temps constant fonction de comparaison pour éviter les attaques de synchronisation.

Hachage de Mot de passe avec PHP 5.5

PHP 5.5 a introduit les fonctions de hachage de mot de passe que vous pouvez utiliser pour simplifier la méthode de hachage ci-dessus:

$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 13]);

Et vérification:

if (password_verify($given_password, $db_hash)) {
    // password valid
}

Voir aussi: password_hash(), password_verify()

271
répondu Ja͢ck 2015-05-11 10:44:57

Je pense que cela a déjà été répondu...mais de toute façon, si vous voulez chiffrer / déchiffrer des données, vous ne pouvez pas utiliser SHA256

//Key
$key = 'SuperSecretKey';

//To Encrypt:
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, 'I want to encrypt this', MCRYPT_MODE_ECB);

//To Decrypt:
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $encrypted, MCRYPT_MODE_ECB);
20
répondu romo 2012-06-06 14:37:22

Contexte de réponse et explication

Pour comprendre cette question, vous devez d'abord comprendre ce QU'est SHA256. SHA256 est une fonction de hachage cryptographique . Une fonction de hachage cryptographique est une fonction à Sens Unique, dont la sortie est cryptographiquement sécurisée. Cela signifie qu'il est facile de calculer un hachage (équivalent au chiffrement des données), mais difficile d'obtenir l'entrée d'origine en utilisant le hachage (équivalent au déchiffrement des données). Puisque l'utilisation D'une fonction de hachage cryptographique signifie que le décryptage est infaisable sur le plan informatique, vous ne pouvez donc pas effectuer de décryptage avec SHA256.

Ce que vous voulez utiliser est une fonction bidirectionnelle, mais plus spécifiquement, un chiffrement par bloc . Une fonction qui permet à la fois le cryptage et le déchiffrement des données. Les fonctions mcrypt_encrypt et mcrypt_decrypt utilisent par défaut L'algorithme Blowfish. L'utilisation de PHP de mcrypt peut être trouvée dans ce manuel . Une liste dedéfinitions de chiffrement pour sélectionner le chiffrement utilisé par mcrypt existe également. Un wiki sur Blowfish peut être trouvé à Wikipedia. Un chiffrement par bloc crypte l'entrée dans des blocs de taille et de position connues avec une clé connue, de sorte que les données peuvent ensuite être déchiffrées à l'aide de la clé. C'est ce que SHA256 ne peut pas vous fournir.

Code

$key = 'ThisIsTheCipherKey';

$ciphertext = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, 'This is plaintext.', MCRYPT_MODE_CFB);

$plaintext = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $encrypted, MCRYPT_MODE_CFB);
14
répondu cytinus 2014-08-06 12:15:51

Voici un exemple utilisant openssl_encrypt

//Encryption:
$textToEncrypt = "My Text to Encrypt";
$encryptionMethod = "AES-256-CBC";
$secretHash = "encryptionhash";
$iv = mcrypt_create_iv(16, MCRYPT_RAND);
$encryptedText = openssl_encrypt($textToEncrypt,$encryptionMethod,$secretHash, 0, $iv);

//Decryption:
$decryptedText = openssl_decrypt($encryptedText, $encryptionMethod, $secretHash, 0, $iv);
print "My Decrypted Text: ". $decryptedText;
7
répondu Vivek 2016-05-19 20:28:31

Il m'a fallu un certain temps pour comprendre, comment ne pas obtenir un false lors de l'utilisation de openssl_decrypt() et obtenir le chiffrement et le décryptage.

    // cryptographic key of a binary string 16 bytes long (because AES-128 has a key size of 16 bytes)
    $encryption_key = '58adf8c78efef9570c447295008e2e6e'; // example
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
    $encrypted = openssl_encrypt($plaintext, 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, $iv);
    $encrypted = $encrypted . ':' . base64_encode($iv);

    // decrypt to get again $plaintext
    $parts = explode(':', $encrypted);
    $decrypted = openssl_decrypt($parts[0], 'aes-256-cbc', $encryption_key, OPENSSL_RAW_DATA, base64_decode($parts[1])); 

Si vous souhaitez passer la chaîne cryptée via une URL, vous devez urlencode la chaîne:

    $encrypted = urlencode($encrypted);

Pour mieux comprendre ce qui se passe, lisez:

Pour générer des clés longues de 16 octets, vous pouvez utiliser:

    $bytes = openssl_random_pseudo_bytes(16);
    $hex = bin2hex($bytes);

Pour voir les messages d'erreur de openssl, vous pouvez utiliser: echo openssl_error_string();

J'espère que ça aide.

0
répondu Kai Noack 2017-09-08 21:26:30
     function my_simple_crypt( $string, $action = 'e' ) {
        // you may change these values to your own
        $secret_key = 'my_simple_secret_key';
        $secret_iv = 'my_simple_secret_iv';

        $output = false;
        $encrypt_method = "AES-256-CBC";
        $key = hash( 'sha256', $secret_key );
        $iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );

        if( $action == 'e' ) {
            $output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );
        }
        else if( $action == 'd' ){
            $output = openssl_decrypt( base64_decode( $string ), $encrypt_method, $key, 0, $iv );
        }

        return $output;
    }
0
répondu gaurav daxini 2018-04-20 07:12:05