我想按块加密/解密文件,因为文件大小可能非常大(50-100Mb)。我在stack overflow上找到了加密类的代码并稍稍改了一下:
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);
我的问题是块大小如何影响加密/解密过程?它是否与分组密码模式和填充相关联?如何通过块加密数据?
也许我应该为此目的使用另一个密码?
答案 0 :(得分:1)
它是否与分组密码模式和填充相关联?
专注于。
也许我应该为此目的使用另一个密码?
您可以这样做并使用类似流的密码模式,例如CTR,不需要填充。
或者您可以处理您选择的块大小。它应该可以被你的密码的任何mcrypt_get_block_size()返回整除。
基本上,分组密码模式也会将数据分成“块”,只有那些被称为块 - 因此,块大小。只要条件$dataSize % $blockSize !== 0
为真,最后一个块将用NUL字节填充(通过MCrypt)。
然后,在解密阶段,MCrypt 不会修剪这些NUL字节,并且您的图像被破坏。