phpmcrypt:按块加密/解密数据。为什么结果取决于块的大小?

phpmcrypt:按块加密/解密数据。为什么结果取决于块的大小?,php,encryption,mcrypt,Php,Encryption,Mcrypt,我想按块加密/解密文件,因为文件大小可能相当大(50-100Mb)。我在上找到了加密类的代码,并对其进行了一些更改: class filecrypt{ var $_CHUNK_SIZE; var $_CHIPHER; var $_MODE; function __construct($chipher, $mode){ $this->_CHUNK_SIZE = 100*1024; // 100Kb $this->_CHIPHER = $chipher; $t

我想按块加密/解密文件,因为文件大小可能相当大(50-100Mb)。我在上找到了加密类的代码,并对其进行了一些更改:

class filecrypt{

var $_CHUNK_SIZE;
var $_CHIPHER;
var $_MODE;

function __construct($chipher, $mode){
    $this->_CHUNK_SIZE = 100*1024; // 100Kb
    $this->_CHIPHER = $chipher;
    $this->_MODE = $mode;
}

public function setChunkSize($value)
{
    $this->_CHUNK_SIZE = $value;
}

public function encrypt($string, $key, $vector){
    $key = pack('H*', $key);
    if (extension_loaded('mcrypt') === true) return mcrypt_encrypt($this->_CHIPHER, substr($key, 0, mcrypt_get_key_size($this->_CHIPHER, $this->_MODE)), $string, $this->_MODE, $vector);
    return false;
}

public function decrypt($string, $key, $vector){
    $key = pack('H*', $key);
    if (extension_loaded('mcrypt') === true) return mcrypt_decrypt($this->_CHIPHER, substr($key, 0, mcrypt_get_key_size($this->_CHIPHER, $this->_MODE)), $string, $this->_MODE, $vector);
    return false;
}

public function encryptFileChunks($source, $destination, $key, $vector){
    return $this->cryptFileChunks($source, $destination, $key, 'encrypt', $vector);
}

public function decryptFileChunks($source, $destination, $key, $vector){
    return $this->cryptFileChunks($source, $destination, $key, 'decrypt', $vector);
}

private function cryptFileChunks($source, $destination, $key, $op, $vector){

    if($op != "encrypt" and $op != "decrypt") return false;

    $buffer = '';
    $inHandle = fopen($source, 'rb');
    $outHandle = fopen($destination, 'wb+');

    if ($inHandle === false) return false;
    if ($outHandle === false) return false;

    while(!feof($inHandle)){
        $buffer = fread($inHandle, $this->_CHUNK_SIZE);
        if($op == "encrypt") $buffer = $this->encrypt($buffer, $key, $vector);
        elseif($op == "decrypt") $buffer = $this->decrypt($buffer, $key, $vector);
        fwrite($outHandle, $buffer);
    }
    fclose($inHandle);
    fclose($outHandle);
    return true;
}

public function printFileChunks($source, $key, $vector){

    $buffer = '';
    $inHandle = fopen($source, 'rb');

    if ($inHandle === false) return false;

    while(!feof($inHandle)){
        $buffer = fread($inHandle, $this->_CHUNK_SIZE);
        $buffer = $this->decrypt($buffer, $key, $vector);
        echo $buffer;
    }
    return fclose($inHandle);
}
}
所以,我在脚本中测试了这个类:

$chipher = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_CFB;

$filecrypt = new filecrypt($chipher, $mode);
$key = '3da541559918a808c2402bba5012f6c60b27661c'; // Your encryption key

$vectorSize = mcrypt_get_iv_size($chipher, $mode);
$vector  =   mcrypt_create_iv($vectorSize, MCRYPT_DEV_URANDOM);

//Encrypt file
$filecrypt->setChunkSize(8*1024);
$filecrypt->encryptFileChunks(APPLICATION_PATH.'/../data/resources/img1.jpg', APPLICATION_PATH.'/../data/resources/img1_en.jpg', $key, $vector);

//Decrypt file
$filecrypt->setChunkSize(8*1024);
$filecrypt->decryptFileChunks(APPLICATION_PATH.'/../data/resources/img1_en.jpg', APPLICATION_PATH.'/../data/resources/img1_res.jpg', $key, $vector);
一切正常,恢复的图像与源图像完全相同

但若我为加密和解密过程设置了不同的块大小,那个么恢复的图像将被破坏。这是源图像:

这是加密/解密后以不同块大小还原的图像:

下面是一个代码:

$chipher = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_CFB;

$filecrypt = new filecrypt($chipher, $mode);
$key = '3da541559918a808c2402bba5012f6c60b27661c'; // Your encryption key

$vectorSize = mcrypt_get_iv_size($chipher, $mode);
$vector  =   mcrypt_create_iv($vectorSize, MCRYPT_DEV_URANDOM);

//Encrypt file
$filecrypt->setChunkSize(8*1024);
$filecrypt->encryptFileChunks(APPLICATION_PATH.'/../data/resources/img1.jpg', APPLICATION_PATH.'/../data/resources/img1_en.jpg', $key, $vector);

//Decrypt file
$filecrypt->setChunkSize(4*1024);
$filecrypt->decryptFileChunks(APPLICATION_PATH.'/../data/resources/img1_en.jpg', APPLICATION_PATH.'/../data/resources/img1_res.jpg', $key, $vector);
我的问题是块大小如何影响加密/解密过程?它是否与分组密码模式和填充连接?如何按块加密数据

也许我应该用另一个密码

它是否与分组密码模式和填充连接

恰到好处

也许我应该用另一个密码

您可以这样做,并使用类似流的密码模式,如CTR,它不需要填充

或者你可以考虑你选择的块大小。它应该可以被密码的返回值整除

基本上,分组密码模式也会将您的数据分割成“块”,只有那些才会被称为块-因此,块大小。只要条件
$dataSize%$blockSize!==0
为真,最后一个块将用NUL字节填充(由MCrypt填充)

然后,在解密阶段,MCrypt不修剪这些NUL字节,图像就会损坏