【发布时间】:2019-03-08 22:29:18
【问题描述】:
我知道这是个老话题,但我玩了一点我的小型 OTP 库,我想问你一个建议。一切都很完美,但我确信没有管理员希望看到类似“php_value memory_limit 500000M”的东西:D。
我不打算重新发明轮子,但我真的试图找到一些用于加密数据的库,我不会对 AES、mcrypt 等感到满意,因为如果加密数据的大小小于大小,则没有 100% 的安全性的关键。如果有人能告诉我正确的方向,我会非常高兴。
我的库运行良好,但看起来对于 1 GB 的文件,我至少需要一个服务器机房;)而且因为我正在研究商业解决方案,具有“一点”更高的安全级别,我不会满足于其他图书馆。
非常感谢所有答案。
就是这样:
<?php
/** OtpFile - One time pad base64 file encryption
* @author Tomas Stofik, https://www.tomasstofik.com/
* @copyright 2018 Tomas Stofik
*/
final class OtpFile
{
private static $charSet = array(
'+','/','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s',
't','u','v','w','x','y','z'
);
public static function encryptFile(
$originalFilePath,
$encryptedFilePath,
$keyFilePath)
{
if(!self::existsFile($keyFilePath) || !self::existsFile($encryptedFilePath)) {
if($originalFileData = self::existsFile($originalFilePath)) {
$originalFileBase64Data = base64_encode($originalFileData);
$originalFileBase64DataLength = strlen($originalFileBase64Data) - 1;
$originalFileBase64DataArray = str_split($originalFileBase64Data);
$encryptedData = NULL;
$encryptedDataKey = NULL;
for ($i=0; $i <= $originalFileBase64DataLength; $i++) {
$randKey = rand(0, sizeOf(self::$charSet) - 1);
$arrayKey = array_search(
$originalFileBase64DataArray[$i],
self::$charSet
);
if($randKey > $arrayKey) {
$str='-'.($randKey - $arrayKey);
} elseif($randKey < $arrayKey) {
$str = ($randKey + $arrayKey);
} else {
$str = $randKey;
}
$encryptedData .= self::$charSet[$randKey];
$encryptedDataKey .= $str.';';
}
$encryptedDataString = $encryptedData;
$encryptedDataKeyString = $encryptedDataKey;
if(!self::existsFile($keyFilePath)) {
file_put_contents($keyFilePath, $encryptedDataKeyString);
}
if(!self::existsFile($encryptedFilePath)) {
file_put_contents($encryptedFilePath, $encryptedDataString);
}
return 'OK';
} else {
return 'Source file not exists';
}
} else {
return 'Encrypted data already exists';
}
}
public static function decryptFile(
$encryptedFilePath,
$keyFilePath,
$decryptedFilePath)
{
$keyFileData = self::existsFile($keyFilePath);
$encryptedFileData = self::existsFile($encryptedFilePath);
$encryptedFileDataLength = strlen($encryptedFileData) - 1;
if($encryptedFileData && $keyFileData) {
$encryptedFileDataArray = str_split($encryptedFileData);
$keyFileDataArray = explode(';',$keyFileData);
$decryptedData = NULL;
for ($i=0; $i <= $encryptedFileDataLength; $i++) {
$positionCurrent = array_search($encryptedFileDataArray[$i], self::$charSet);
$positionEncrypted = $keyFileDataArray[$i];
if ($positionEncrypted == $positionCurrent) {
$move = $positionEncrypted;
} elseif($positionEncrypted < 0) {
$move=$positionEncrypted + $positionCurrent;
} elseif($positionEncrypted > 0) {
$move=$positionEncrypted - $positionCurrent;
} else {
$move='0';
}
$decryptedData .= self::$charSet[$move];
}
if(!self::existsFile($decryptedFilePath)) {
file_put_contents(
$decryptedFilePath,
base64_decode(
$decryptedData
)
);
return 'OK';
} else {
return 'Decrypted data already exists';
}
}
}
private static function existsFile($filePath)
{
$fileData = @file_get_contents($filePath);
if($fileData) {
return $fileData;
}
return FALSE;
}
}
/* Using
$originalFilePath = 'original.jpg';
$keyFilePath = 'Otp_Key_' . $originalFilePath;
$encryptedFilePath = 'Otp_Data_' . $originalFilePath;
$decryptedFilePath = 'Otp_Decrypted_' . $originalFilePath;
echo OtpFile::encryptFile($originalFilePath, $encryptedFilePath, $keyFilePath);
echo OtpFile::decryptFile($encryptedFilePath, $keyFilePath, $decryptedFilePath);
*/
【问题讨论】:
-
php_value memory_limit 500000M我在一个地方有ini_set('memory_limit', '3G')。但它需要它> 120,000,000 行数据库数据才能做到这一点(这是一个在晚上运行的 cron 作业 :-p )....另外,这只是服务器 RAM 的4%。 -
尝试加密 14GB Matroska (*.mkv) 电影以及每周 10 000 个用户。例如:原始图像文件 2.0MB 加密文件大小:2.8MB 加密密钥大小:8.0MB 您对此有何看法? ;)
-
"我不打算重新发明轮子,但我确实试图找到一些用于加密数据的库,但我不会对 AES、mcrypt 等感到满意,因为如果大小为加密的数据小于密钥的大小。如果有人能告诉我正确的方向,我会很高兴。我向您保证,由整个专业密码学家团队创建的经过同行评审的加密可以提出比您更好的方法。 Do not roll your own.
-
为了加密大文件,您可以分块加密/解密它们,而不是整体加密。这取决于您的用例。而且我至少会使用 AES,比如 PHPSecLib
-
ceejayoz:我当然知道,这就是我写轮子的原因。但我不会为那个解决方案花费 1 MIO 我的朋友 ;)
标签: php encryption base64 one-time-password