26

我正在寻找一种将 .txt 文件加密为 zip 的方法,但要以安全的密码保护方式进行。我的目标是将此文件通过电子邮件发送给我,而任何人都无法阅读附件的内容。

有没有人知道一个简单的,最重要的是,安全的方法来完成这个?我可以创建 zip 档案,但我不知道如何加密它们,或者,这有多安全。

4

5 回答 5

21

从 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";
}
?>

但是您也可以通过索引而不是名称设置加密方法,并且您可以基于每个文件设置每个密码......以及使用新支持的加密选项指定较弱的加密选项。

这个例子练习了这些更复杂的选项。

<?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";
}
?>

由于 libzip 1.2.0 引入了对加密的支持,因此启用了对 zip 加密的底层支持。因此,您将需要 php 7.2 和 libzip 7.2 才能运行此代码...希望此注释“很快”会在此答案上变得很简单

于 2017-12-01T08:49:15.403 回答
20

注意:此答案推荐一种已知不安全的加密方法,即使密码良好。请参阅评论中的链接AES 上的 Winzip QAphp 7.2(和libzip 1.2.0 )支持 in-php AES zip 加密,这意味着这个答案也很快就会过时。在此之前,请参阅此答案,了解如何调用 7z 而不是支持 winzip 的 AES 加密的 zip 命令

你可以使用这个:

<?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 )

这种安全性可以被蛮力攻击、字典攻击等破坏。但这并不容易,特别是如果你选择了一个长而难以猜到的密码。

于 2009-03-14T16:45:17.007 回答
4

尽管 PHP 是一门成熟的语言,但没有足够的方法(不包括自定义扩展或类似的东西)来用纯 PHP 完成如此简单的任务。

您还可以做的是等到PHP 7.2可用于生产(因为ZipArchive::setEncryptionName已实现(感谢 Pierre 和 Remi))。

但是,在那之前你也可以尝试将php_zip >= 1.14.0 移植到 PHP < 7.2,但是目前没有可用的编译二进制文件,所以你必须自己编译它并尝试是否可能(我相信它是)。

PS我会尝试一下,但我的电脑上现在没有VS2015+。

于 2017-07-19T22:16:41.283 回答
0

越来越多的工具支持 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 版本中可用。

于 2009-03-22T10:17:02.397 回答
-4

我就是这样做的。这是一个excel,但它是一样的。

  • 让 php 创建一个随机代号。
  • 将代号保存在db 或retrieve.php 包含的文件中。
  • 给自己邮寄代号。

  • 通过网络访问retrieve.php?codename=[codename]

  • 让 php 检查代号是否正确。(甚至可能是年龄)。
  • 根据需要发送给您的数据在内存中创建 excel/文本文件。
  • 通过添加带有代号的本地密码(只有您知道)来创建加密代码。(我说添加但也可以混合或异或或子...)
  • 使用创建的加密代码即时加密。
  • 从 db 或配置文件中删除代号。
  • 在邮件中返回此加密文档(压缩或不压缩)。
  • 也许在邮件中添加代号的前两个字符,以了解要使用的本地完整代号。

  • 使用本地解密脚本对下载的文件进行解码。使用相同的代号/密码算法来创建解密密钥。

我使用乱码-aes-php。(https://github.com/ivantcholakov/gibberish-aes-php
因为那时我可以在客户端解码器上使用https://github.com/mdp/gibberish-aes作为 javascript (我想快速在浏览器中查看)。

于 2014-01-01T21:53:51.587 回答