Шифрование / дешифрование файла с Mcrypt - PullRequest
22 голосов
/ 15 марта 2010

Пытаюсь написать пару функций, которые будут шифровать или дешифровать файл, и я использую класс, найденный здесь, чтобы попытаться выполнить это:

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

Представленная ниже функция шифрования, кажется, работает, поскольку она, по-видимому, шифрует файл и помещает его в предполагаемый каталог. Я пытаюсь расшифровать файл сейчас, и он просто умирает с сообщением «Не удалось завершить расшифровку» (который там закодирован ...) В журналах ошибок php ничего нет, поэтому я не уверен, почему он не работает , но поскольку mcrypt для меня совершенно новый, я более чем склонен полагать, что я что-то здесь не так делаю ...

Вот функции:

//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);
    }

Ответы [ 4 ]

55 голосов
/ 15 марта 2010

Попробуйте этот класс PHP5 для шифрования с использованием mcrypt. В этом случае используется шифрование AES. Вы захотите изменить ключ для каждого сайта, на котором вы его используете. Если вы его не используете, по крайней мере, это может помочь вам написать свою собственную версию.

<?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");
    }
}

Использование:

$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

Примечания:

  • Этот класс небезопасен для использования с двоичными данными (которые могут заканчиваться байтами NUL)
  • Этот класс не обеспечивает аутентифицированное шифрование.
2 голосов
/ 09 декабря 2016

Вы не должны использовать Mcrypt для шифрования / дешифрования данных. Как показано в вашем вопросе и в принятом ответе, данные не аутентифицированы, что означает, что они станут жертвами выбранных атак шифрованного текста.

Кроме того, были приложены огромные усилия для того, чтобы разработчики правильно собирали криптографические примитивы. Таким образом, вместо Mcrypt вы должны использовать libsodium для своих проектов PHP. libsodium - это вилка NaCl. NaCl / libsodium написан для устранения многих криптографических ошибок, в которые попадают разработчики, таких как временные атаки с проверкой MAC-тегов.

Mcrypt устарел в PHP 7.1, и libsodim является предпочтительным способом обработки криптографии в PHP.

Использование libsodium в вашем PHP-проекте просто и безопасно. Скотт Аркишевский (Scott Arciszewski) написал обширную книгу по использованию libsodium с PHP на https://paragonie.com/book/pecl-libsodium.. Это стоит прочитать всем, кто занимается PHP-криптографией.

2 голосов
/ 05 декабря 2014

Хотя ответ Джона хорош, использование кодировки base64 просто для устранения проблемы безопасности двоичных файлов излишне, и ваши зашифрованные файлы будут на 33% больше оригинальных. Вот моя PHP-реализация формата файла AES Crypt, который прозрачно решает все вышеперечисленные проблемы.

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

Это бинарный сейф и включает аутентифицированное шифрование. Поскольку он использует формат файла шифрования aes с открытым исходным кодом (.aes), он полностью совместим с другим программным обеспечением .aes.

https://www.aescrypt.com/

Интерфейс довольно прост, шифруете ли вы или расшифровываете. Вы просто даете ему исходный файл и пароль.

1 голос
/ 21 сентября 2013

CakePHP имеет довольно хорошую реализацию Рэйндаэля. Я не размещаю код прямо здесь, потому что не уверен в юридических последствиях.

Вот API-документы для метода Security::rijndael().

Если кодируется файл, вам нужно будет base64_encode() перед вызовом этого метода с помощью encrypt и base64_decode() после вызова этого метода с помощью decrypt

...