web-dev-qa-db-fra.com

Chiffrement / déchiffrement de fichiers avec Mcrypt

J'essaie d'écrire quelques fonctions qui crypteront ou décrypteront un fichier et j'utilise la classe trouvée ici pour essayer d'accomplir ceci:

http://www.itnewb.com/v/PHP-Encryption-Decryption-Using-the-MCrypt-Library-libmcrypt

La fonction de cryptage ci-dessous semble fonctionner, en ce sens qu'elle semble crypter le fichier et le placer dans le répertoire prévu. J'essaie de décrypter le fichier maintenant, et il meurt juste avec le message "Échec du décryptage" (qui est codé là-dedans ...) Il n'y a rien dans les journaux d'erreurs php, donc je ne sais pas pourquoi il échoue , mais comme mcrypt est entièrement nouveau pour moi, je suis plus que enclin à croire que je fais quelque chose de mal ici ...

Voici les fonctions:

//ENCRYPT FILE
    function encryptFile() {
        global $cryptastic;
        $pass = PGPPASS;
        $salt = PGPSALT;
        $key = $cryptastic->pbkdf2($pass, $salt, 1000, 32) or die("Failed to generate secret key.");

        if ($handle = opendir(PATH.'/ftpd')) {
            while (false !== ($file = readdir($handle))) {
                if ($file != "." && $file != "..") {
                    $newfile = PATH.'/encrypted/'.$file.'.txt';
                    $msg = file_get_contents(PATH.'/ftpd/'.$file);
                    $encrypted = $cryptastic->encrypt($msg, $key) or die("Failed to complete encryption.");
                    $nfile = fopen($newfile, 'w');
                    fwrite($nfile, $encrypted);
                    fclose($nfile);
                    unlink(PATH.'/ftpd/'.$file);

                }
            }
            closedir($handle);
        }       


//DECRYPT FILE
    function inFTP() {
        global $cryptastic;
        $pass = PGPPASS;
        $salt = PGPSALT;
        $key = $cryptastic->pbkdf2($pass, $salt, 1000, 32) or die("Failed to generate secret key.");

        if ($handle = opendir(PATH.'/encrypted')) {
            while (false !== ($file = readdir($handle))) {
                if ($file != "." && $file != "..") {
                    $newfile = PATH.'/decrypted/'.$file;
                    $msg = PATH.'/encrypted/'.$file;
                    $decrypted = $cryptastic->decrypt($msg, $key) or die("Failed to complete decryption.");
                    $nfile = fopen($newfile, 'w');
                    fwrite($nfile, $decrypted);
                    fclose($nfile);
                    //unlink(PATH.'/encrypted/'.$file);

                }
            }
            closedir($handle);
        }       
        //$crypt->decrypt($file);
    }
22
whitman6732

Essayez cette classe PHP5 pour le chiffrement à l'aide de mcrypt. Dans ce cas, il utilise le cryptage AES. Vous voudrez changer la clé de chaque site sur lequel vous l'utilisez. Si vous ne l'utilisez pas au moins, cela peut vous guider dans la rédaction de votre propre version.

<?php

class Encryption
{
    const CIPHER = MCRYPT_RIJNDAEL_128; // Rijndael-128 is AES
    const MODE   = MCRYPT_MODE_CBC;

    /* Cryptographic key of length 16, 24 or 32. NOT a password! */
    private $key;
    public function __construct($key) {
        $this->key = $key;
    }

    public function encrypt($plaintext) {
        $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE);
        $iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
        $ciphertext = mcrypt_encrypt(self::CIPHER, $this->key, $plaintext, self::MODE, $iv);
        return base64_encode($iv.$ciphertext);
    }

    public function decrypt($ciphertext) {
        $ciphertext = base64_decode($ciphertext);
        $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE);
        if (strlen($ciphertext) < $ivSize) {
            throw new Exception('Missing initialization vector');
        }

        $iv = substr($ciphertext, 0, $ivSize);
        $ciphertext = substr($ciphertext, $ivSize);
        $plaintext = mcrypt_decrypt(self::CIPHER, $this->key, $ciphertext, self::MODE, $iv);
        return rtrim($plaintext, "\0");
    }
}

Usage:

$key = /* CRYPTOGRAPHIC!!! key */;
$crypt = new Encryption($key);
$encrypted_string = $crypt->encrypt('this is a test');
$decrypted_string = $crypt->decrypt($encrypted_string); // this is a test

Remarques:

  • Cette classe n'est pas sûre pour une utilisation avec des données binaires (qui peuvent se terminer en octets NUL)
  • Cette classe ne fournit pas de chiffrement authentifié.
55
John Conde

Vous ne devez pas utiliser Mcrypt pour crypter/décrypter des données. Comme indiqué dans votre question et dans la réponse acceptée, les données ne sont pas authentifiées, ce qui signifie qu'elles seront victimes des attaques de texte chiffré choisies.

De plus, beaucoup d'efforts ont été faits pour s'assurer que les développeurs assemblent correctement les primitives cryptographiques. En tant que tel, au lieu de Mcrypt, vous devriez utiliser libsodium pour vos projets PHP. Libsodium est une fourchette de NaCl. NaCl/libsodium est écrit pour supprimer beaucoup des pièges cryptographiques que les développeurs se trouvent , comme le chronométrage des attaques avec vérification des balises MAC.

Mcrypt est déconseillé dans PHP 7.1, et libsodim est le moyen préféré pour gérer la cryptographie en PHP.

Utiliser libsodium dans votre projet PHP est facile et sécurisé. Scott Arciszewski a écrit un livre électronique complet sur l'utilisation de libsodium avec PHP sur https://paragonie.com/book/pecl-libsodium . Cela vaut la peine d'être lu pour tous ceux qui font de la cryptographie PHP.

2
Aaron Toponce

Bien que la réponse de Johns soit bonne, utiliser l'encodage base64 juste pour résoudre le problème de sécurité binaire est exagéré et rendra vos fichiers cryptés 33% plus volumineux que l'original. Voici mon PHP Implémentation du format de fichier AES Crypt qui résout tous les problèmes ci-dessus de manière transparente.

https://github.com/philios33/PHP-AES-File-Encryption

Il est binaire et comprend un cryptage authentifié. Puisqu'il utilise le format de fichier crypté open source aes (.aes), il est entièrement compatible avec d'autres logiciels .aes.

https://www.aescrypt.com/

L'interface est assez simple, que vous chiffriez ou déchiffriez. Vous lui donnez simplement un fichier source et un mot de passe.

2
Phil

CakePHP a une assez bonne implémentation de rijndael. Je ne publie pas de code directement ici car je ne suis pas sûr des ramifications légales.

Voici les documents api pour la méthode Security::rijndael().

Si vous encodez un fichier, vous voudrez base64_encode() avant d'appeler cette méthode avec 'encrypt', et base64_decode() après avoir appelé cette méthode avec 'decrypt "

1
rynop