【发布时间】:2009-03-14 16:24:56
【问题描述】:
我正在寻找一种将 .txt 文件加密为 zip 的方法,但要以安全的密码保护方式进行。我的目标是将此文件通过电子邮件发送给我,而任何人都无法阅读附件的内容。
有没有人知道一个简单的,最重要的是,安全的方法来完成这个?我可以创建 zip 存档,但我不知道如何加密它们,或者,这有多安全。
【问题讨论】:
标签: php encryption zip
我正在寻找一种将 .txt 文件加密为 zip 的方法,但要以安全的密码保护方式进行。我的目标是将此文件通过电子邮件发送给我,而任何人都无法阅读附件的内容。
有没有人知道一个简单的,最重要的是,安全的方法来完成这个?我可以创建 zip 存档,但我不知道如何加密它们,或者,这有多安全。
【问题讨论】:
标签: php encryption zip
从 php 7.2(几小时前发布)开始,正确的做法是使用 ZipArchive 原生 php 代码中包含的附加功能。 (感谢abraham-tugalov 指出这一变化即将到来)
现在简单的答案看起来像这样:
<?php
$zip = new ZipArchive();
if ($zip->open('test.zip', ZipArchive::CREATE) === TRUE) {
$zip->setPassword('secret_used_as_default_for_all_files'); //set default password
$zip->addFile('thing1.txt'); //add file
$zip->setEncryptionName('thing1.txt', ZipArchive::EM_AES_256); //encrypt it
$zip->addFile('thing2.txt'); //add file
$zip->setEncryptionName('thing2.txt', ZipArchive::EM_AES_256); //encrypt it
$zip->close();
echo "Added thing1 and thing2 with the same password\n";
} else {
echo "KO\n";
}
?>
但是您也可以通过索引而不是名称来设置加密方法,并且您可以基于每个文件设置每个密码...以及指定较弱的加密选项,使用newly supported encryption options.
本示例练习了这些更复杂的选项。
<?php
$zip = new ZipArchive();
if ($zip->open('test.zip', ZipArchive::CREATE) === TRUE) {
//being here means that we were able to create the file..
//setting this means that we do not need to pass in a password to every file, this will be the default
$zip->addFile('thing3.txt');
//$zip->setEncryptionName('thing3.txt', ZipArchive::EM_AES_128);
//$zip->setEncryptionName('thing3.txt', ZipArchive::EM_AES_192);
//you should just use ZipArchive::EM_AES_256 unless you have super-good reason why not.
$zip->setEncryptionName('thing3.txt', ZipArchive::EM_AES_256, 'password_for_thing3');
$zip->addFile('thing4.txt');
//or you can also use the index (starting at 0) of the file...
//which means the following line should do the same thing...
//but just referencing the text.txt by index instead of name..
//$zip->setEncryptionIndex(1, ZipArchive::EM_AES_256, 'password_for_thing_4'); //encrypt thing4, using its index instead of its name...
$zip->close();
echo "Added thing3 and thing4 with two different passwords\n";
} else {
echo "KO\n";
}
?>
启用了对 zip 加密的底层支持,因为 libzip 1.2.0 引入了对加密的支持。因此,您将需要 php 7.2 和 libzip 7.2 才能运行此代码...希望此注释“很快”会在此答案上变得很简单
【讨论】:
注意:此答案推荐一种已知的加密方法 不安全,即使密码很好。请see link from comments 和the Winzip QA on AES。支持 in-php AES zip 加密 与php 7.2(和libzip 1.2.0)一起到达,这意味着 答案也将很快过时。在那之前see this answer for how to call out to 7z instead of the zip command, which supports winzip's AES encryption。
你可以用这个:
<?php echo system('zip -P pass file.zip file.txt'); ?>
pass 是密码,file.txt 会被压缩成file.zip。这应该适用于 Windows 和 Linux,您只需要获得适用于 Windows 的免费版本的 zip (http://www.info-zip.org/Zip.html#Win32)
这种安全性可以被蛮力攻击、字典攻击等破坏。但这并不容易,特别是如果你选择了一个长且难以猜到的密码。
【讨论】:
虽然 PHP 是一门成熟的语言,但没有足够的方法(不包括自定义扩展或类似的东西)来用纯 PHP 完成如此简单的任务。
您还可以做的是等到PHP 7.2 可用于生产(因为ZipArchive::setEncryptionName 已实现(感谢 Pierre 和 Remi))。
但是,在那之前您也可以尝试将php_zip >= 1.14.0 移植到 PHP
PS 我想试试,但我的电脑上现在没有 VS2015+。
【讨论】:
越来越多的工具支持 AES 加密的 ZIP 文件。它有效,它是安全的。
EDIT2:您可以使用 PHP 中的 DotNetZip 从 PHP 动态生成 AES 加密的 zip 存档。 DotNetZip 是一个 .NET 库,专为 .NET 语言(C#、VB 等)而设计。它只能在 Windows 上运行 :(。但 DotNetZip 使用 AES,而且它是免费的,并且可以在 PHP 上运行。
这是我使用的代码。 (Win32 上的 PHP v5.2.9)
<?php
try
{
$fname = "zip-generated-from-php-" . date('Y-m-d-His') . ".zip";
$zipOutput = "c:\\temp\\" . $fname;
$zipfact = new COM("Ionic.Zip.ZipFile");
$zip->Name = $zipOutput;
$dirToZip= "c:\\temp\\psh";
# Encryption: 3 => 256-bit AES.
# 2 => 128-bit AES.
# 1 => PKZIP (Weak).
# 0 => None
$zip->Encryption = 3;
$zip->Password = "AES-Encryption-Is-Secure";
$zip->AddDirectory($dirToZip);
$zip->Save();
$zip->Dispose();
if (file_exists($zipOutput))
{
header('Cache-Control: no-cache, must-revalidate');
header('Content-Type: application/x-zip');
header('Content-Disposition: attachment; filename=' . $fname);
header('Content-Length: ' . filesize($zipOutput));
readfile($zipOutput);
unlink($zipOutput);
}
else
{
echo '<html>';
echo ' <head>';
echo ' <title>Calling DotNetZip from PHP through COM</title>';
echo ' <link rel="stylesheet" href="basic.css"/>';
echo ' </head>';
echo '<body>';
echo '<h2>Whoops!</h2>' . "<br/>\n";
echo '<p>The file was not successfully generated.</p>';
echo '</body>';
echo '</html>';
}
}
catch (Exception $e)
{
echo '<html>';
echo ' <head>';
echo ' <title>Calling DotNetZip from PHP through COM</title>';
echo ' <link rel="stylesheet" href="basic.css"/>';
echo ' </head>';
echo '<body>';
echo '<h2>Whoops!</h2>' . "<br/>\n";
echo '<p>The file was not successfully generated.</p>';
echo '<p>Caught exception: ', $e->getMessage(), '</p>', "\n";
echo '<pre>';
echo $e->getTraceAsString(), "\n";
echo '</pre>';
echo '</body>';
echo '</html>';
}
?>
我必须修改 DotNetZip 以使其与 PHP 一起工作:我必须使 Name 属性为读/写,并且我必须使其可被 COM 调用。此更改首先在 v1.8.2.3 release 中提供。
【讨论】:
我就是这样做的。 是用excel,但是是一样的。
将代号邮寄给自己。
通过网络访问retrieve.php?codename=[codename]
可以在邮件中添加代号的前两个字符,以了解要使用的本地完整代号。
使用本地解密脚本对下载的文件进行解码。使用相同的代号/密码算法创建解密密钥。
我使用乱码-aes-php。 (https://github.com/ivantcholakov/gibberish-aes-php)
因为那时我可以在客户端解码器上使用https://github.com/mdp/gibberish-aes 作为javascript(对于我想在浏览器中快速浏览的东西)。
【讨论】: