这是我的问题,
我想加密在某些情况下可能很长的JSON文件。 (有时包含Base64格式的图像。)
在以下测试服务器上,一切正常:
另一方面,在以下服务器上(打算使用..),加密不能使用超过65535个字符,服务器似乎崩溃了。
CPU有限制吗?
php.ini的参数会影响吗?
我在多台服务器上测试了完全相同的代码,并且在提到的两个Synology上都无法正常工作...
这是我的加密/解密课程:
class PHP_AES_Cipher {
private static $OPENSSL_CIPHER_NAME = "AES-256-CBC"; //Name of OpenSSL Cipher
private static $CIPHER_KEY_LEN = 32;
static function encrypt($key, $iv, $data) {
if (strlen($key) < PHP_AES_Cipher::$CIPHER_KEY_LEN) {
$key = str_pad("$key", PHP_AES_Cipher::$CIPHER_KEY_LEN, "0");
} else if (strlen($key) > PHP_AES_Cipher::$CIPHER_KEY_LEN) {
$key = substr($str, 0, PHP_AES_Cipher::$CIPHER_KEY_LEN);
}
$encodedEncryptedData = base64_encode(openssl_encrypt($data, PHP_AES_Cipher::$OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv));
$encodedIV = base64_encode($iv);
$encryptedPayload = $encodedEncryptedData.":".$encodedIV;
return $encryptedPayload;
}
static function decrypt($key, $data) {
if (strlen($key) < PHP_AES_Cipher::$CIPHER_KEY_LEN) {
$key = str_pad("$key", PHP_AES_Cipher::$CIPHER_KEY_LEN, "0");
} else if (strlen($key) > PHP_AES_Cipher::$CIPHER_KEY_LEN) {
$key = substr($str, 0, PHP_AES_Cipher::$CIPHER_KEY_LEN);
}
$parts = explode(':', $data); //Separate Encrypted data from iv.
$decryptedData = openssl_decrypt(base64_decode($parts[0]), PHP_AES_Cipher::$OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, base64_decode($parts[1]));
return $decryptedData;
}
}
我这样使用它:
$data = PHP_AES_Cipher::encrypt($key, $iv, $data);
和
$data = PHP_AES_Cipher::decrypt($key, $iv, $data);
假设一切都可以在某些服务器上运行,我认为代码没有问题。我已经检查了Apache和PHP日志,没有任何报告。
我已经搜寻了几天,却不了解问题的原因。
希望有人可以帮助我:-)
答案 0 :(得分:1)
将其大块
这就是我的工作(使用PHPSecLib2)
/**
* AES encrypt large files using streams and chunking
*
* @param resource $stream
* @param resource $outputStream
* @param string $key
* @throws SecExecption
*/
function streamSymEncode($stream, &$outputStream, $key, $chunkSize = 10240){
if(!is_resource($stream)) throw new Execption('Resource expected[input]');
rewind($stream); //make sure the stream is rewound
if(!is_resource($outputStream)) throw new Execption('Resource expected[output]');
$Cipher = new AES(AES::MODE_CBC);
$Cipher->setKey($key);
//create the IV
$iv = Random::string($Cipher->getBlockLength() >> 3);
$Cipher->setIV($iv);
if(strlen($iv_base64 = rtrim(base64_encode($iv), '=')) != 22) throw new Execption('IV lenght check fail');
fwrite($outputStream, $iv_base64.'$'); //add the IV for later use when we decrypt
while(!feof($stream)){
$chunk = fread($stream, $chunkSize);
fwrite($outputStream, rtrim(base64_encode($Cipher->encrypt($chunk)),'=').':');
}
$stat = fstat($outputStream);
ftruncate($outputStream, $stat['size'] - 1); //trim off the last character, hanging ':'
}
/**
* AES decrypt large files that were previously encrypted using streams and chunking
*
* @param resource $stream
* @param resource $outputStream
* @param string $key
* @throws SecExecption
*/
function streamSymDecode($stream, &$outputStream, $key){
if(!is_resource($stream)) throw new Execption('Resource expected[input]');
rewind($stream); //make sure the stream is rewound
if(!is_resource($outputStream)) throw new Execption('Resource expected[output]');
$Cipher = new AES(AES::MODE_CBC);
$Cipher->setKey($key);
$iv = base64_decode(fread($stream, 22) . '==');
$Cipher->setIV($iv);
fread($stream, 1); //advance 1 for the $
$readLine = function(&$stream){
$line = '';
while(false !== ($char = fgetc($stream))){
if($char == ':') break;
$line .= $char;
}
return $line;
};
while(!feof($stream)){
$chunk = $readLine($stream);
$decrypted = $Cipher->decrypt(base64_decode($chunk.'=='));
if(!$decrypted) throw new Execption('Failed to decode!');
fwrite($outputStream, $decrypted);
}
}
它需要两个文件流资源,例如您从fopen
获得的资源和一个密钥。然后,它使用相同的加密方式,但将文件分割成$chunkSize
,然后将其与:
分开,并在进行解码时,将其分割成块并重新组装所有内容。
它像这样结束(
IV$firstChunk:secondChunk:thirdChunk
这样,您就不会用尽内存来加密大型文件。
请注意,这是我使用的一个更大的类的一部分,所以我不得不修剪一些东西并进行一些未测试的更改。
https://github.com/phpseclib/phpseclib
干杯。