2009-03-14 48 views
18

Estoy buscando una manera de cifrar un archivo .txt en un archivo comprimido, pero de una manera segura protegida por contraseña. Mi objetivo es enviarme este archivo por correo electrónico, sin que nadie pueda leer el contenido del archivo adjunto.Crear un archivo comprimido cifrado con PHP

¿Alguien sabe de una forma fácil, y sobre todo, segura de lograr esto? Puedo crear archivos zip, pero no sé cómo encriptarlos, o cuán seguro es esto.

Respuesta

17

Nota: esta respuesta recomienda un método criptográfico conocido inseguro, incluso con una buena contraseña. Por favor, see link from comments y . Soporte para en-php cifrado AES zip llega con php 7.2 (y libzip 1.2.0), lo que significa que esta respuesta pronto también estará desactualizada. Hasta entonces see this answer for how to call out to 7z instead of the zip command, which supports winzip's AES encryption.

Puede utilizar esta:

<?php echo system('zip -P pass file.zip file.txt'); ?> 

Cuando pase es la contraseña, y file.txt se comprimen en file.zip. Esto debería funcionar en Windows y Linux, solo necesita obtener una versión gratuita de zip para Windows (http://www.info-zip.org/Zip.html#Win32)

Este tipo de seguridad se puede romper con ataques de fuerza bruta, ataques de diccionario y etc. Pero no es tan fácil, especialmente si elige una contraseña larga y difícil de adivinar.

+0

gracias, intentaré esto. está en un servidor linux estoy trabajando, por lo que el complemento no será necesario. – Digits

+3

El cifrado ZIP es bastante débil, hay ataques que producen una contraseña activa (si no necesariamente la misma contraseña que se usó originalmente) en relativamente poco tiempo. – bobince

+3

Esta respuesta es muy peligrosa. La encriptación utilizada por esta respuesta es terriblemente débil. * No * es la encriptación moderna basada en AES. –

1

Cada vez son más las herramientas que admiten archivos ZIP cifrados por AES. Funciona, es seguro.

EDIT2: Puede usar DotNetZip desde PHP para generar dinámicamente archivos zip encriptados AES desde PHP. DotNetZip es una biblioteca .NET diseñada para lenguajes .NET (C#, VB, etc.). Se ejecuta sólo en Windows :(. Pero DotNetZip hace AES, y es gratis, y funciona desde PHP.

Este es el código que he usado. (V5.2.9 PHP en Win32)

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

?> 

I Tuve que modificar DotNetZip para que funcionara con PHP: tuve que hacer que la propiedad Nombre fuera de lectura/escritura, y tuve que hacer que COM-llamara. Este cambio está primero disponible en el v1.8.2.3 release.

+0

y ¿sabes cómo puedo usar esto en un script php? ¡muchas gracias! – Digits

+1

si ejecuta PHP en Windows, existe DotNetZip (http://dotnetzip.codeplex.com) que admite cremalleras cifradas AES. PHP puede invocar componentes .NET. badda bing, badda boom. – Cheeso

+1

desafortunadamente, la mayoría de mis servidores se ejecutan en Linux. pero puedo usar esta solución para los que están en Windows. ¡muchas gracias! – Digits

-1

Así lo hice Es con un excel, pero es lo mismo.

  • Deja que php cree un nombre en clave al azar.
  • Guarde el nombre clave en db o en un archivo para ser incluido por retrieve.php.
  • Envíese el nombre en clave.

  • Acceso a través de la web de retrieve.php? Nombre en clave = [nombre clave]

  • Deje que cheque si php nombre en clave es correcta. (tal vez incluso es la edad).
  • Cree el archivo Excel/text en la memoria a partir de los datos que se le deben enviar.
  • Cree un código de cifrado agregando una contraseña local (que solo usted conoce) con el nombre en clave. (Digo agregar, pero también puede ser mixta o xor-ed o substr ...)
  • Encripta sobre la marcha con el código de encriptación creado.
  • Elimina el nombre de código del archivo db o config.
  • Devuelva este documento cifrado por correo (con cremallera o sin el tamaño).
  • Quizás agregue dos primeros caracteres de codename en el correo para saber qué nombre de código completo local usar.

  • Utilice un script de descifrado local para decodificar el archivo descargado. Use el mismo algoritmo de nombre de código/contraseña para crear una clave de descifrado.

Yo uso gibberish-aes-php. (https://github.com/ivantcholakov/gibberish-aes-php)
Porque entonces puedo usar https://github.com/mdp/gibberish-aes como javascript en un decodificador cliente (para cosas que quiero echar un vistazo rápido en un navegador).

3

Aunque PHP es un lenguaje maduro, no existe un método adecuado (excluyendo la extensión personalizada o algo así) para lograr una tarea tan simple con PHP puro.
Lo que también puede hacer, es esperar hasta que PHP 7.2 esté disponible para la producción (se implementa cuz ZipArchive::setEncryptionName (gracias a Pierre y Remi)).
Pero, hasta entonces, también puede tratar de portar php_zip> = 1.14.0 a PHP < 7.2, pero actualmente no hay binarios compilados disponibles, por lo que debe compilarlo usted mismo y probar si es posible (creo es).
p.s. Lo probaría, pero no tengo VS2015 + en mi PC ahora mismo.

0

A partir de php 7.2 (que se lanzó hace unas horas), la forma correcta de hacerlo es utilizar la funcionalidad adicional incluida en ZipArchive código nativo php. (Gracias a abraham-tugalov por señalar que este cambio iba a venir)

Ahora la respuesta simple es como la siguiente:

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

Pero también puede establecer el método de cifrado por el índice y no el nombre, y se puede configure cada contraseña por archivo ... y especifique las opciones de cifrado más débiles, usando newly supported encryption options.

Este ejemplo ejerce estas opciones más complejas.

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

El soporte subyacente para el cifrado zip está habilitado porque libzip 1.2.0 introdujo el soporte para el cifrado. Por lo tanto, necesitará tener php 7.2 y libzip 7.2 para ejecutar este código ... Esperamos que esta nota sea confusa en esta respuesta "muy pronto"

Cuestiones relacionadas