Comment crypter et décrypter une chaîne PHP?

225

Ce que je veux dire est:

Original String + Salt or Key --> Encrypted String
Encrypted String + Salt or Key --> Decrypted (Original String)

Peut-être quelque chose comme:

"hello world!" + "ABCD1234" --> Encrypt --> "2a2ffa8f13220befbe30819047e23b2c" (may be, for e.g)
"2a2ffa8f13220befbe30819047e23b2c" --> Decrypt with "ABCD1234" --> "hello world!"
  • En PHP, comment pouvez-vous faire cela?

Tentative d'utilisation Crypt_Blowfish, mais cela n'a pas fonctionné pour moi.

夏 期 劇場
la source
35
@Rogue Il ne veut pas de hachage, il veut un chiffrement symétrique (comme AES), il ne sait tout simplement pas comment ça s'appelle. (Et maintenant il le fait :))
Patashu
dans quelle mesure doit-il être sécurisé?
3
@ 夏 期 劇場, Vous ne «salez» pas le cryptage symétrique, vous utilisez une clé. Une clé doit être gardée secrète. Un sel peut être public sans nuire à la sécurité (tant que le sel de chacun est différent), et c'est un terme utilisé pour hacher les mots de passe.
Patashu
2
Vous avez besoin d'un Salt (clé privée), d'une clé publique et d'un algorithme de cryptage comme AES-256: wpy.me/blog/15-encrypt-and-decrypt-data-in-php-using-aes-256
wappy
8
@CristianFlorea L'auteur de ce billet de blog utilise des termes qui n'ont tout simplement aucun sens dans le contexte du chiffrement symétrique. Il n'y a pas de clé publique avec AES, ni de sel. Il n'y a qu'une seule clé; il faut le garder secret. Dans certains modes de fonctionnement, il existe un IV qui n'a pas besoin d'être secret, mais un IV n'est pas un sel (selon le mode, il peut avoir des exigences très différentes) et n'a pas besoin d'être secret, tandis que la clé de cryptage réelle ne peut absolument pas être publique. La clé publique / privée s'applique à la cryptographie asymétrique, mais n'a rien à voir avec AES.
cpast

Réponses:

410

Avant de faire quoi que ce soit d'autre, cherchez à comprendre la différence entre le cryptage et l' authentification , et pourquoi vous voulez probablement un cryptage authentifié plutôt qu'un simple cryptage .

Pour implémenter le cryptage authentifié, vous souhaitez crypter puis MAC. L'ordre de chiffrement et d'authentification est très important! L'une des réponses existantes à cette question a fait cette erreur; comme le font de nombreuses bibliothèques de cryptographie écrites en PHP.

Vous devez éviter d'implémenter votre propre cryptographie et utiliser à la place une bibliothèque sécurisée écrite et révisée par des experts en cryptographie.

Mise à jour: PHP 7.2 fournit désormais libsodium ! Pour une meilleure sécurité, mettez à jour vos systèmes pour utiliser PHP 7.2 ou supérieur et suivez uniquement les conseils de libsodium dans cette réponse.

Utilisez libsodium si vous avez un accès PECL (ou sodium_compat si vous voulez libsodium sans PECL); sinon ...
Utilisez le cryptage de désamorçage / php ; ne lancez pas votre propre cryptographie!

Les deux bibliothèques liées ci-dessus facilitent et simplifient l'implémentation du chiffrement authentifié dans vos propres bibliothèques.

Si vous souhaitez toujours écrire et déployer votre propre bibliothèque de cryptographie, contrairement à la sagesse conventionnelle de tous les experts en cryptographie sur Internet, voici les étapes à suivre.

Chiffrement:

  1. Chiffrez en utilisant AES en mode CTR. Vous pouvez également utiliser GCM (ce qui supprime le besoin d'un MAC séparé). De plus, ChaCha20 et Salsa20 (fournis par libsodium ) sont des chiffrements de flux et n'ont pas besoin de modes spéciaux.
  2. Sauf si vous avez choisi GCM ci-dessus, vous devez authentifier le texte chiffré avec HMAC-SHA-256 (ou, pour les chiffrements de flux, Poly1305 - la plupart des API libsodium le font pour vous). Le MAC devrait couvrir l'IV ainsi que le texte chiffré!

Décryptage:

  1. Sauf si Poly1305 ou GCM est utilisé, recalculez le MAC du texte chiffré et comparez-le avec le MAC envoyé à l'aide hash_equals(). S'il échoue, abandonnez.
  2. Déchiffrez le message.

Autres considérations de conception:

  1. Ne compressez jamais rien. Le texte chiffré n'est pas compressible; la compression du texte en clair avant le chiffrement peut entraîner des fuites d'informations (par exemple CRIME et BREACH sur TLS).
  2. Assurez-vous d'utiliser mb_strlen()et d' mb_substr()utiliser le '8bit'mode de jeu de caractères pour éviter les mbstring.func_overloadproblèmes.
  3. Les IV devraient être générés à l' aide d'un CSPRNG ; Si vous utilisez mcrypt_create_iv(), NE PAS UTILISERMCRYPT_RAND !
  4. Sauf si vous utilisez une construction AEAD, TOUJOURS crypter puis MAC!
  5. bin2hex(), base64_encode()Etc. peut entraîner une fuite d' informations sur vos clés de chiffrement via synchronisation du cache. Évitez-les si possible.

Même si vous suivez les conseils donnés ici, beaucoup de choses peuvent mal tourner avec la cryptographie. Demandez toujours à un expert en cryptographie d'examiner votre implémentation. Si vous n'avez pas la chance d'être des amis personnels avec un étudiant en cryptographie de votre université locale, vous pouvez toujours essayer le forum Cryptography Stack Exchange pour obtenir des conseils.

Si vous avez besoin d'une analyse professionnelle de votre implémentation, vous pouvez toujours embaucher une équipe réputée de consultants en sécurité pour revoir votre code de cryptographie PHP (divulgation: mon employeur).

Important: quand ne pas utiliser le chiffrement

Ne cryptez pas les mots de passe . Vous souhaitez les hacher à la place, en utilisant l'un de ces algorithmes de hachage de mot de passe:

N'utilisez jamais une fonction de hachage à usage général (MD5, SHA256) pour le stockage des mots de passe.

Ne cryptez pas les paramètres d'URL . Ce n'est pas le bon outil pour le travail.

Exemple de chiffrement de chaîne PHP avec Libsodium

Si vous êtes sur PHP <7.2 ou si vous n'avez pas installé libsodium, vous pouvez utiliser sodium_compat pour obtenir le même résultat (quoique plus lentement).

<?php
declare(strict_types=1);

/**
 * Encrypt a message
 * 
 * @param string $message - message to encrypt
 * @param string $key - encryption key
 * @return string
 * @throws RangeException
 */
function safeEncrypt(string $message, string $key): string
{
    if (mb_strlen($key, '8bit') !== SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
        throw new RangeException('Key is not the correct size (must be 32 bytes).');
    }
    $nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);

    $cipher = base64_encode(
        $nonce.
        sodium_crypto_secretbox(
            $message,
            $nonce,
            $key
        )
    );
    sodium_memzero($message);
    sodium_memzero($key);
    return $cipher;
}

/**
 * Decrypt a message
 * 
 * @param string $encrypted - message encrypted with safeEncrypt()
 * @param string $key - encryption key
 * @return string
 * @throws Exception
 */
function safeDecrypt(string $encrypted, string $key): string
{   
    $decoded = base64_decode($encrypted);
    $nonce = mb_substr($decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');

    $plain = sodium_crypto_secretbox_open(
        $ciphertext,
        $nonce,
        $key
    );
    if (!is_string($plain)) {
        throw new Exception('Invalid MAC');
    }
    sodium_memzero($ciphertext);
    sodium_memzero($key);
    return $plain;
}

Puis pour le tester:

<?php
// This refers to the previous code block.
require "safeCrypto.php"; 

// Do this once then store it somehow:
$key = random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES);
$message = 'We are all living in a yellow submarine';

$ciphertext = safeEncrypt($message, $key);
$plaintext = safeDecrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Halite - Libsodium simplifié

L'un des projets sur lesquels j'ai travaillé est une bibliothèque de cryptage appelée Halite , qui vise à rendre libsodium plus facile et plus intuitif.

<?php
use \ParagonIE\Halite\KeyFactory;
use \ParagonIE\Halite\Symmetric\Crypto as SymmetricCrypto;

// Generate a new random symmetric-key encryption key. You're going to want to store this:
$key = new KeyFactory::generateEncryptionKey();
// To save your encryption key:
KeyFactory::save($key, '/path/to/secret.key');
// To load it again:
$loadedkey = KeyFactory::loadEncryptionKey('/path/to/secret.key');

$message = 'We are all living in a yellow submarine';
$ciphertext = SymmetricCrypto::encrypt($message, $key);
$plaintext = SymmetricCrypto::decrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Toute la cryptographie sous-jacente est gérée par libsodium.

Exemple avec désamorçage / cryptage php

<?php
/**
 * This requires https://github.com/defuse/php-encryption
 * php composer.phar require defuse/php-encryption
 */

use Defuse\Crypto\Crypto;
use Defuse\Crypto\Key;

require "vendor/autoload.php";

// Do this once then store it somehow:
$key = Key::createNewRandomKey();

$message = 'We are all living in a yellow submarine';

$ciphertext = Crypto::encrypt($message, $key);
$plaintext = Crypto::decrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

Remarque : Crypto::encrypt()renvoie une sortie codée hexadécimale.

Gestion des clés de chiffrement

Si vous êtes tenté d'utiliser un "mot de passe", arrêtez tout de suite. Vous avez besoin d'une clé de cryptage aléatoire de 128 bits, et non d'un mot de passe mémorable humain.

Vous pouvez stocker une clé de chiffrement pour une utilisation à long terme comme ceci:

$storeMe = bin2hex($key);

Et, à la demande, vous pouvez le récupérer comme suit:

$key = hex2bin($storeMe);

Je recommande fortement de simplement stocker une clé générée de manière aléatoire pour une utilisation à long terme au lieu de tout type de mot de passe comme clé (ou pour dériver la clé).

Si vous utilisez la bibliothèque de Defuse:

"Mais je veux vraiment utiliser un mot de passe."

C'est une mauvaise idée, mais d'accord, voici comment le faire en toute sécurité.

Tout d'abord, générez une clé aléatoire et stockez-la dans une constante.

/**
 * Replace this with your own salt! 
 * Use bin2hex() then add \x before every 2 hex characters, like so:
 */
define('MY_PBKDF2_SALT', "\x2d\xb7\x68\x1a\x28\x15\xbe\x06\x33\xa0\x7e\x0e\x8f\x79\xd5\xdf");

Notez que vous ajoutez du travail supplémentaire et que vous pouvez simplement utiliser cette constante comme clé et vous épargner beaucoup de chagrin d'amour!

Utilisez ensuite PBKDF2 (comme cela) pour dériver une clé de chiffrement appropriée de votre mot de passe plutôt que de chiffrer directement avec votre mot de passe.

/**
 * Get an AES key from a static password and a secret salt
 * 
 * @param string $password Your weak password here
 * @param int $keysize Number of bytes in encryption key
 */
function getKeyFromPassword($password, $keysize = 16)
{
    return hash_pbkdf2(
        'sha256',
        $password,
        MY_PBKDF2_SALT,
        100000, // Number of iterations
        $keysize,
        true
    );
}

N'utilisez pas seulement un mot de passe à 16 caractères. Votre clé de cryptage sera cassée de façon comique.

Scott Arciszewski
la source
3
Ne cryptez pas les mots de passe , hachez-les avec password_hash()et vérifiez-les avec password_verify().
Scott Arciszewski
2
"Ne compressez jamais rien." Vous voulez dire comme HTTP, spdy et d'autres protocoles? Avant TLS? Beaucoup de conseils absolutistes?
Tiberiu-Ionuț Stan
1
@ScottArciszewski J'aime votre commentaire sur la clé "// Faites-le une fois puis stockez-le en quelque sorte:" .. en quelque sorte, lol :)) et que diriez-vous de stocker cette "clé" (qui est un objet) sous forme de chaîne ordinaire, codée en dur? J'ai besoin de la clé elle-même, sous forme de chaîne. Puis-je l'obtenir de cet objet d'une manière ou d'une autre? Merci
Andrew
2
Thx, je devais juste modifier une ligne afin de faire fonctionner vos exemples de sodium:function getKeyFromPassword($password, $keysize = \Sodium\CRYPTO_SECRETBOX_KEYBYTES)
Alexey Ozerov
1
Hou la la! +1 pour avoir mentionné de ne pas crypter les paramètres d'URL. J'ai vraiment aimé l'article que vous fournissez: paragonie.com/blog/2015/09/…
Lynnell Emmanuel Neri
73

Je suis en retard à la fête, mais en cherchant la bonne façon de le faire, je suis tombé sur cette page, c'était l'un des meilleurs résultats de recherche Google, donc j'aimerais partager mon avis sur le problème, que je considère comme étant à jour au moment de la rédaction de cet article (début 2017). A partir de PHP 7.1.0, le mcrypt_decryptet mcrypt_encryptva être obsolète, donc la construction d'un code à l'épreuve du temps devrait utiliser openssl_encrypt et openssl_decrypt

Vous pouvez faire quelque chose comme:

$string_to_encrypt="Test";
$password="password";
$encrypted_string=openssl_encrypt($string_to_encrypt,"AES-128-ECB",$password);
$decrypted_string=openssl_decrypt($encrypted_string,"AES-128-ECB",$password);

Important : Ceci utilise le mode ECB , qui n'est pas sécurisé. Si vous voulez une solution simple sans suivre un cours intensif en ingénierie de la cryptographie, ne l'écrivez pas vous-même, utilisez simplement une bibliothèque.

Vous pouvez également utiliser d'autres méthodes de déchiquetage, en fonction de vos besoins en matière de sécurité. Pour connaître les méthodes de déchiquetage disponibles, consultez la fonction openssl_get_cipher_methods .

Emil Borconi
la source
10
Merci, je suis surpris que cette réponse simple et claire ne soit pas plus votée. Je préfère ne pas lire une discussion de 10 pages sur le sujet comme la meilleure réponse quand tout ce que je veux c'est crypter / décrypter une simple chaîne.
laurent
4
Ce n'est pas une réponse sûre. Le mode ECB ne doit pas être utilisé. Si vous voulez une "réponse simple et claire", utilisez simplement une bibliothèque .
Scott Arciszewski
2
@ScottArciszewski, oui j'avoue avoir parlé trop rapidement en cherchant du code simple. Depuis, j'ai ajouté un IV et j'utilise CBC dans mon propre code, ce qui est assez bon pour mon utilisation.
laurent
Lisez ceci et reconsidérez . Avec le mode CBC, un attaquant peut changer complètement le message. Si le message est un fichier, un attaquant peut retourner les bits et faire apparaître calc.exe. Les risques de chiffrement non authentifié sont graves.
Scott Arciszewski
7
Tout dépend du cas d'utilisation! Il y a des cas où c'est parfaitement FIN. Par exemple, je veux passer un paramètre GET de page en page, disons, prod_id=123mais je ne veux tout simplement pas rendre 123 lisible pour tout le monde, mais même s'ils pouvaient le lire, ce ne serait pas un problème. Un attaquant pouvant remplacer le 123 par une valeur personnalisée ne causera aucun dommage, il / elle ne pourra obtenir des détails que sur tout autre produit, mais Joe Average User n'aura aucune idée sur la manière d'obtenir des détails pour produit 124 par exemple. Pour un scénario comme celui-ci, c'est une solution parfaite, pour la sécurité, c'est non!
Emil Borconi
43

Ce qu'il ne faut pas faire

AVERTISSEMENT:
cette réponse utilise la BCE . ECB n'est pas un mode de cryptage, c'est seulement un bloc de construction. L'utilisation d'ECB comme démontré dans cette réponse ne chiffre pas réellement la chaîne en toute sécurité. N'utilisez pas ECB dans votre code. Voir la réponse de Scott pour une bonne solution.

Je l'ai sur moi. En fait, j'ai trouvé une réponse sur Google et j'ai juste modifié quelque chose. Le résultat est cependant complètement incertain.

<?php
define("ENCRYPTION_KEY", "!@#$%^&*");
$string = "This is the original data string!";

echo $encrypted = encrypt($string, ENCRYPTION_KEY);
echo "<br />";
echo $decrypted = decrypt($encrypted, ENCRYPTION_KEY);

/**
 * Returns an encrypted & utf8-encoded
 */
function encrypt($pure_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);
    return $encrypted_string;
}

/**
 * Returns decrypted original string
 */
function decrypt($encrypted_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv);
    return $decrypted_string;
}
?>
夏 期 劇場
la source
8
Vous pouvez soit utiliser "MCRYPT_MODE_CBC" au lieu de "MCRYPT_MODE_ECB" pour assurer plus de sécurité.
Parixit
10
Ramesh, c'est parce que vous obtenez les données chiffrées brutes. Vous pouvez obtenir une version plus agréable des données cryptées en utilisant base64, comme ceci: base64_encode(encrypt($string))- Pour les décrypter:decrypt(base64_decode($encrypted))
mendezcode
82
AVERTISSEMENT: ce n'est pas sûr . Le mode ECB ne doit pas être utilisé pour les chaînes, ECB ne prend pas de IV, ce n'est pas authentifié, il utilise un ancien chiffrement (Blowfish) au lieu d'AES, la clé n'est pas binaire, etc. etc. La communauté SO devrait vraiment arrêter le cryptage de vote / décryptage qui "fonctionne" simplement et démarre le vote en amont des réponses connues pour être sécurisées. Si vous ne le savez pas, ne votez pas.
Maarten Bodewes du
3
J'ai déjà fait cela en mcrypt_encryptremplaçant l'exemple de code de : php.net/manual/en/function.mcrypt-encrypt.php . Notez que le réviser maintenant devrait probablement avoir un rtrimcaractère for "\0"à la fin.
Maarten Bodewes
4
La bonne réponse est d'utiliser quelque chose comme defuse / php-encryption au lieu d'écrire votre propre code mcrypt.
Scott Arciszewski
18

Pour le framework Laravel

Si vous utilisez le framework Laravel, il est plus facile de crypter et décrypter avec des fonctions internes.

$string = 'Some text to be encrypted';
$encrypted = \Illuminate\Support\Facades\Crypt::encrypt($string);
$decrypted_string = \Illuminate\Support\Facades\Crypt::decrypt($encrypted);

var_dump($string);
var_dump($encrypted);
var_dump($decrypted_string);

Remarque: veillez à définir une chaîne aléatoire de 16, 24 ou 32 caractères dans l'option clé du fichier config / app.php. Sinon, les valeurs chiffrées ne seront pas sécurisées.

Somnath Muluk
la source
1
Bien sûr, il peut être facile à utiliser. Mais est-ce sûr? Comment résout-il les problèmes sur stackoverflow.com/a/30159120/781723 ? Utilise-t-il un cryptage authentifié? Évite-t-il les vulnérabilités des canaux secondaires et assure-t-il des contrôles d'égalité à temps constant? Utilise-t-il une clé vraiment aléatoire plutôt qu'un mot de passe / phrase de passe? Utilise-t-il un mode de fonctionnement approprié? Génère-t-il correctement des IV aléatoires?
DW
10

Actualisé

Version prête pour PHP 7. Il utilise la fonction openssl_encrypt de la bibliothèque PHP OpenSSL .

class Openssl_EncryptDecrypt {
    function encrypt ($pure_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);
        $ciphertext_raw = openssl_encrypt($pure_string, $cipher, $encryption_key, $options, $iv);
        $hmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        return $iv.$hmac.$ciphertext_raw;
    }
    function decrypt ($encrypted_string, $encryption_key) {
        $cipher     = 'AES-256-CBC';
        $options    = OPENSSL_RAW_DATA;
        $hash_algo  = 'sha256';
        $sha2len    = 32;
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = substr($encrypted_string, 0, $ivlen);
        $hmac = substr($encrypted_string, $ivlen, $sha2len);
        $ciphertext_raw = substr($encrypted_string, $ivlen+$sha2len);
        $original_plaintext = openssl_decrypt($ciphertext_raw, $cipher, $encryption_key, $options, $iv);
        $calcmac = hash_hmac($hash_algo, $ciphertext_raw, $encryption_key, true);
        if(function_exists('hash_equals')) {
            if (hash_equals($hmac, $calcmac)) return $original_plaintext;
        } else {
            if ($this->hash_equals_custom($hmac, $calcmac)) return $original_plaintext;
        }
    }
    /**
     * (Optional)
     * hash_equals() function polyfilling.
     * PHP 5.6+ timing attack safe comparison
     */
    function hash_equals_custom($knownString, $userString) {
        if (function_exists('mb_strlen')) {
            $kLen = mb_strlen($knownString, '8bit');
            $uLen = mb_strlen($userString, '8bit');
        } else {
            $kLen = strlen($knownString);
            $uLen = strlen($userString);
        }
        if ($kLen !== $uLen) {
            return false;
        }
        $result = 0;
        for ($i = 0; $i < $kLen; $i++) {
            $result |= (ord($knownString[$i]) ^ ord($userString[$i]));
        }
        return 0 === $result;
    }
}

define('ENCRYPTION_KEY', '__^%&Q@$&*!@#$%^&*^__');
$string = "This is the original string!";

$OpensslEncryption = new Openssl_EncryptDecrypt;
$encrypted = $OpensslEncryption->encrypt($string, ENCRYPTION_KEY);
$decrypted = $OpensslEncryption->decrypt($encrypted, ENCRYPTION_KEY);
夏 期 劇場
la source
1
C'est une version meilleure et beaucoup plus sûre. Merci, cela fonctionne aussi comme prévu.
1
comment créez-vous et où conservez-vous la clé de cryptage?
user2800464
7

Note historique: Ceci a été écrit au moment de PHP4. C'est ce que nous appelons maintenant le «code hérité».

J'ai laissé cette réponse à des fins historiques - mais certaines méthodes sont désormais obsolètes, la méthode de cryptage DES n'est pas une pratique recommandée, etc.

Je n'ai pas mis à jour ce code pour deux raisons: 1) je ne travaille plus à la main avec les méthodes de chiffrement en PHP, et 2) ce code remplit toujours le but pour lequel il était destiné: démontrer le concept minimal et simpliste du fonctionnement du chiffrement en PHP.

Si vous trouvez une source de type "cryptage PHP pour les nuls" tout aussi simpliste qui peut faire démarrer les gens dans 10 à 20 lignes de code ou moins, faites-le moi savoir dans les commentaires.

Au-delà de cela, profitez de cet épisode classique de la réponse de chiffrement minimaliste PHP4 de la première époque.


Idéalement, vous avez - ou pouvez avoir - accès à la bibliothèque PHP mcrypt, car elle est certainement populaire et très utile pour une variété de tâches. Voici un aperçu des différents types de cryptage et quelques exemples de code: Techniques de cryptage en PHP

//Listing 3: Encrypting Data Using the mcrypt_ecb Function 

<?php 
echo("<h3> Symmetric Encryption </h3>"); 
$key_value = "KEYVALUE"; 
$plain_text = "PLAINTEXT"; 
$encrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $plain_text, MCRYPT_ENCRYPT); 
echo ("<p><b> Text after encryption : </b>"); 
echo ( $encrypted_text ); 
$decrypted_text = mcrypt_ecb(MCRYPT_DES, $key_value, $encrypted_text, MCRYPT_DECRYPT); 
echo ("<p><b> Text after decryption : </b>"); 
echo ( $decrypted_text ); 
?> 

Quelques avertissements:

1) N'utilisez jamais de chiffrement réversible ou "symétrique" lorsqu'un hachage unidirectionnel fera l'affaire.

2) Si les données sont vraiment sensibles, comme les numéros de carte de crédit ou de sécurité sociale, arrêtez; vous avez besoin de plus que n'importe quel morceau de code simple, mais vous avez plutôt besoin d'une bibliothèque de chiffrement conçue à cet effet et d'un temps considérable pour rechercher les méthodes nécessaires. De plus, la cryptographie logicielle représente probablement <10% de la sécurité des données sensibles. C'est comme recâbler une centrale nucléaire - acceptez que la tâche soit dangereuse et difficile et au-delà de vos connaissances si c'est le cas. Les sanctions financières peuvent être immenses, il vaut donc mieux utiliser un service et leur assumer la responsabilité.

3) Tout type de cryptage facilement implémentable, tel qu'énuméré ici, peut raisonnablement protéger les informations moyennement importantes que vous souhaitez garder à l'abri des regards indiscrets ou limiter l'exposition en cas de fuite accidentelle / intentionnelle. Mais vu comment la clé est stockée en texte brut sur le serveur Web, s'ils peuvent obtenir les données, ils peuvent obtenir la clé de déchiffrement.

Quoi qu'il en soit, amusez-vous :)

BrianH
la source
9
Eww, DES. Où est AES?
Patashu
2
Merci! Mais certains problèmes. Je reçois M�������f=�_=des caractères étranges comme cryptés. Je ne peux pas obtenir de caractères simples? Comme: 2a2ffa8f13220befbe30819047e23b2c. De plus, ne puis-je pas changer la LONGUEUR de $key_value(fixée à 8 ???) et la LONGUEUR de sortie $encrypted_text? (ne peut-il pas être long de 32 ou 64 ou quoi que ce soit de plus ??)
夏 期 劇場
3
@ 夏 期 劇場 Le résultat du chiffrement est des données binaires. Si vous avez besoin qu'il soit lisible par l'homme, utilisez-le en base64 ou en encodage hexadécimal. 'Je ne peux pas changer la longueur de la valeur de clé?' Différents algorithmes de chiffrement symétriques ont des exigences différentes pour la valeur de clé. 'et la LONGUEUR de la sortie ...' La longueur du texte chiffré doit être au moins aussi longue que le texte d'origine, sinon il n'y a pas assez d'informations pour recréer le texte d'origine. (Il s'agit d'une application du principe de Pigeonhole.) BTW, vous devez utiliser AES au lieu de DES. Le DES est facilement cassable et n'est plus sécurisé.
Patashu
8
mcrypt_ecb est obsolète depuis PHP 5.5.0. Il est fortement déconseillé de se fier à cette fonction. php.net/manual/en/function.mcrypt-ecb.php
Hafez Divandari
1
@BrianDHall La raison pour laquelle cela obtient toujours des votes négatifs est que le mode ECB n'est pas sûr (utilisez CBC, CTR, GCM ou Poly1305), DES est faible (vous voulez AES, qui est MCRYPT_RIJNDAEL_128) et les textes chiffrés doivent être authentifiés ( hash_hmac(), vérifié avec hash_equals()).
Scott Arciszewski
7

Si vous ne voulez pas utiliser la bibliothèque (que vous devriez), utilisez quelque chose comme ça (PHP 7):

function sign($message, $key) {
    return hash_hmac('sha256', $message, $key) . $message;
}

function verify($bundle, $key) {
    return hash_equals(
      hash_hmac('sha256', mb_substr($bundle, 64, null, '8bit'), $key),
      mb_substr($bundle, 0, 64, '8bit')
    );
}

function getKey($password, $keysize = 16) {
    return hash_pbkdf2('sha256',$password,'some_token',100000,$keysize,true);
}

function encrypt($message, $password) {
    $iv = random_bytes(16);
    $key = getKey($password);
    $result = sign(openssl_encrypt($message,'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv), $key);
    return bin2hex($iv).bin2hex($result);
}

function decrypt($hash, $password) {
    $iv = hex2bin(substr($hash, 0, 32));
    $data = hex2bin(substr($hash, 32));
    $key = getKey($password);
    if (!verify($data, $key)) {
      return null;
    }
    return openssl_decrypt(mb_substr($data, 64, null, '8bit'),'aes-256-ctr',$key,OPENSSL_RAW_DATA,$iv);
}

$string_to_encrypt='John Smith';
$password='password';
$encrypted_string=encrypt($string_to_encrypt, $password);
$decrypted_string=decrypt($encrypted_string, $password);
Ascon
la source
Peut-il être un remplacement de stackoverflow.com/a/16606352/126833 ? J'utilise l'ancien jusqu'à ce que mon hôte soit passé à PHP 7.2.
anjanesh
@anjanesh vous ne pourrez pas décrypter les anciennes données avec celui-ci (différents algorithmes + celui-ci vérifie également la signature)
Ascon
2
Dans votre cas, cela devrait probablement faire:define("ENCRYPTION_KEY", "123456*"); $string = "This is the original data string!"; $encrypted = openssl_encrypt($string, 'BF-ECB', ENCRYPTION_KEY); $decrypted = openssl_decrypt($encrypted,'BF-ECB',ENCRYPTION_KEY);
Ascon
C'est super!
anjanesh
2

Ce sont des méthodes compactes pour crypter / décrypter des chaînes avec PHP en utilisant AES256 CBC :

function encryptString($plaintext, $password, $encoding = null) {
    $iv = openssl_random_pseudo_bytes(16);
    $ciphertext = openssl_encrypt($plaintext, "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, $iv);
    $hmac = hash_hmac('sha256', $ciphertext.$iv, hash('sha256', $password, true), true);
    return $encoding == "hex" ? bin2hex($iv.$hmac.$ciphertext) : ($encoding == "base64" ? base64_encode($iv.$hmac.$ciphertext) : $iv.$hmac.$ciphertext);
}

function decryptString($ciphertext, $password, $encoding = null) {
    $ciphertext = $encoding == "hex" ? hex2bin($ciphertext) : ($encoding == "base64" ? base64_decode($ciphertext) : $ciphertext);
    if (!hash_equals(hash_hmac('sha256', substr($ciphertext, 48).substr($ciphertext, 0, 16), hash('sha256', $password, true), true), substr($ciphertext, 16, 32))) return null;
    return openssl_decrypt(substr($ciphertext, 48), "AES-256-CBC", hash('sha256', $password, true), OPENSSL_RAW_DATA, substr($ciphertext, 0, 16));
}

Usage:

$enc = encryptString("mysecretText", "myPassword");
$dec = decryptString($enc, "myPassword");
Marco Concas
la source
0

Le code ci-dessous fonctionne en php pour toutes les chaînes avec un caractère spécial

   // Encrypt text --

    $token = "9611222007552";

      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);  
      $enc_iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher_method));  
      $crypted_token = openssl_encrypt($token, $cipher_method, $enc_key, 0, $enc_iv) . "::" . bin2hex($enc_iv);
    echo    $crypted_token;
    //unset($token, $cipher_method, $enc_key, $enc_iv);

    // Decrypt text  -- 

    list($crypted_token, $enc_iv) = explode("::", $crypted_token);  
      $cipher_method = 'aes-128-ctr';
      $enc_key = openssl_digest(php_uname(), 'SHA256', TRUE);
      $token = openssl_decrypt($crypted_token, $cipher_method, $enc_key, 0, hex2bin($enc_iv));
    echo   $token;
    //unset($crypted_token, $cipher_method, $enc_key, $enc_iv);
Javed
la source