使用Mcrypt加密/解密文件

whi*_*732 22 php file 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);
    }
Run Code Online (Sandbox Code Playgroud)

Joh*_*nde 55

使用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");
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

$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
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 这个类不适合与二进制数据一起使用(可能以NUL字节结尾)
  • 此类不提供经过身份验证的加密.

  • 我们可以添加强有力的免责声明吗?经过身份验证的加密对于防御主动攻击者来说绝对是必不可少的**.除非你将你的威胁模型贬低到普通脚本小子可以拉下来的范围之外,否则真的没有办法去谈判它,这几乎没有人帮助. (6认同)
  • 那是对的.我在文本文件上运行了这个类,它运行得很好.对于二进制文件,有必要在加密信息之前对信息进行编码.如果文件大于100MB左右,base64_encode将导致性能问题,因此您可能需要考虑将文件拆分为块以进行加密.从安全角度来看,这不是一个理想的解决方案,因为它为恢复部分明文提供了更多机会.但是,它有效. (4认同)
  • "不需要经过身份验证的加密." [错误](http://robertheaton.com/2013/07/29/padding-oracle-attack/).[超级错误](https://tonyarcieri.com/all-the-crypto-code-youve-ever-written-is-probably-broken).经过身份验证的加密不再可以协商. (4认同)
  • 这适用于图像等二进制数据吗? (3认同)
  • 对于二进制数据,我认为你必须在encription之前对它进行base64_encode (3认同)
  • @Motes经过验证的加密应始终是一项要求.没有它,您的实现将成为选择的密文攻击的牺牲品. (3认同)
  • @LayZee这是2016年.没有人应该使用64位分组密码模式来加密数据.有关原因的详细解释,请参阅https://sweet32.info/. (3认同)
  • @rynop注意:我想你的意思是说MCRYPT_DEV_URANDOM(?或者我们与编辑不同步?).我开始在MCRYPT_DEV_RANDOM中使用这个类,遇到了很多性能问题; 切换到MCRYPT_DEV_URANDOM对我来说效果更好(在随机性质量方面需要付出一些代价,但我想我可以忍受它. (2认同)