web-dev-qa-db-ja.com

PHP)を使用して暗号化されたZipアーカイブを作成します

.txtファイルをZipに暗号化する方法を探していますが、安全なパスワードで保護された方法で。私の目標は、添付ファイルの内容を誰も読めないように、このファイルを私に電子メールで送信することです。

これを達成するための簡単で何よりも安全な方法を知っている人はいますか? Zipアーカイブを作成することはできますが、暗号化する方法や、これがどれほど安全かわかりません。

22
Digits

注:この回答では、パスワードが適切であっても、安全でないことがわかっている暗号化方式を推奨しています。 コメントからのリンクを参照 および AESのWinzip QA をお願いします。 in-php AES Zip暗号化のサポートは php 7.2 (および libzip 1.2. )で提供されます。これは、この回答もまもなく古くなることを意味します。それまで winzipのAES暗号化をサポートするZipコマンドの代わりに7zを呼び出す方法については、この回答を参照してください

あなたはこれを使うことができます:

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

この種のセキュリティは、ブルートフォース攻撃や辞書攻撃などによって破られる可能性があります。しかし、特に長くて推測しにくいパスワードを選択した場合は、それほど簡単ではありません。

18
fromvega

Php 7.2(1時間前にリリースされた)の時点で、これを行う正しい方法は、 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暗号化の基本的なサポートが有効になっています。したがって、このコードを実行するには、php7.2とlibzip7.2が必要になります...うまくいけば、このメモはこの答えが「すぐに本物」になることを意味します。

14
ftrotter

PHPは成熟した言語ですが、純粋なPHPでこのような単純なタスクを実行するための適切な方法(カスタム拡張などを除く)はありません。

また、 PHP 7.2 が本番環境で使用可能になるまで待つこともできます( ZipArchive :: setEncryptionName が実装されているため(PierreとRemiに感謝))。

ただし、それまでは、 php_Zip > = 1.14.0をPHP <7.2に移植することもできますが、現在利用可能なコンパイル済みバイナリがないため、次のことを行う必要があります。自分でコンパイルして、可能かどうか試してみてください(可能だと思います)。

PS試してみますが、現在PCにVS2015 +がありません。

4
Abraham Tugalov

ますます多くのツールがAES暗号化Zipファイルをサポートしています。それは動作し、安全です。

EDIT2: DotNetZip from PHPを使用して、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>';
}

?>

PHPで動作するようにDotNetZipを変更する必要がありました。Nameプロパティを読み取り/書き込み可能にし、COM呼び出し可能にする必要がありました。この変更は、 v1.8.2.3リリース で最初に利用可能になります。

0
Cheeso