web-dev-qa-db-ja.com

Mcryptを使用したファイルの暗号化/復号化

ファイルを暗号化または復号化するいくつかの関数を書き込もうとしており、ここにあるクラスを使用してこれを実行しようとしています。

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);
    }
22
whitman6732

Mcryptを使用した暗号化のためにこのPHP5クラスを試してください。この場合、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バイトで終わる可能性があります)で使用するには安全ではありません。
  • このクラスは、認証された暗号化を提供しません。
55
John Conde

データの暗号化/復号化にMcryptを使用しないでください。質問および受け入れられた回答に示されているように、データは認証されていません。つまり、選択した暗号文攻撃の犠牲になります。

さらに、開発者が暗号化プリミティブを正しくまとめるようにするために多大な努力が払われました。そのため、Mcryptの代わりに、PHPプロジェクトにlibsodiumを使用する必要があります。 libsodiumはNaClのフォークです。 NaCl/libsodiumは、MACタグの検証を伴うタイミング攻撃など、開発者が発見する多くの暗号の落とし穴を取り除くために書かれています。

McryptはPHP 7.1で非推奨となり、libsodimはPHPで暗号化を処理するための推奨される方法です。

PHPプロジェクトでlibsodiumを使用するのは簡単で安全です。 Scott Arciszewskiは、 https://paragonie.com/book/pecl-libsodium でPHPでlibsodiumを使用することに関する広範な電子ブックを執筆しました。 PHP暗号化を行う人にとっては読む価値があります。

2
Aaron Toponce

ジョンズの答えは良いですが、バイナリの安全性の問題を修正するためだけにbase64エンコーディングを使用するのはやり過ぎであり、暗号化されたファイルを元のファイルより33%大きくします。ここに私のPHP上記のすべての問題を透過的に解決するAES Cryptファイル形式の実装があります。

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

バイナリセーフであり、認証された暗号化が含まれています。オープンソースのaes暗号化ファイル形式(.aes)を使用しているため、他の.aesソフトウェアと完全に互換性があります。

https://www.aescrypt.com/

暗号化するか復号化するかにかかわらず、インターフェースは非常にシンプルです。ソースファイルとパスワードを与えるだけです。

2
Phil

CakePHP はかなり良い 実装 rijndaelを持っています。法的な影響がわからないため、ここにコードを直接投稿していません。

これはAPIドキュメントですSecurity::rijndael()メソッドの場合。

ファイルをエンコードする場合、 'encrypt'でこのメソッドを呼び出す前にbase64_encode()、 'decryptでこのメソッドを呼び出した後にbase64_decode()が必要になります。 '

1
rynop