¿Cómo usar OpenSSL para cifrar / descifrar archivos?

205

Quiero encriptar y desencriptar un archivo usando una contraseña.

¿Cómo puedo usar OpenSSL para hacer eso?

aF.
fuente
2
Debe derivar una Clave y un IV de la contraseña usando PKCS5_PBKDF2_HMAC. Debe usar las EVP_*funciones para cifrar y descifrar. Vea EVP Symmetric Encryption and Decryption en la wiki de OpenSSL. De hecho, probablemente debería ser autenticado mediante el cifrado, ya que proporciona tanto la confidencialidad y autenticidad. Vea EVP Authenticated Encryption and Decryption en la wiki de OpenSSL.
jww
3
No entiendo por su pregunta por qué quiere OpenSSL. Un comentario a continuación muestra que GPG es mejor, también debido a la seguridad. stackoverflow.com/a/31552829/952234 Voto en contra.
Yaroslav Nikitenko

Respuestas:

261

Advertencia de seguridad : AES-256-CBC no proporciona cifrado autenticado y es vulnerable a los ataques de relleno de oráculo . Deberías usar algo como la edad en su lugar.

Cifrar:

openssl aes-256-cbc -a -salt -in secrets.txt -out secrets.txt.enc

Descifrar:

openssl aes-256-cbc -d -a -in secrets.txt.enc -out secrets.txt.new

Más detalles sobre las diferentes banderas.

Szocske
fuente
18
La respuesta probablemente no sea óptima (a partir de este escrito) dependiendo del caso de uso de OP. Específicamente, los parámetros "-a" probablemente no sean óptimos y la respuesta no explica su uso. "-a" se usa típicamente cuando la salida cifrada se va a transmitir en formato ASCII / texto y tiene el efecto de aumentar el tamaño de salida en comparación con la forma binaria. El póster original no especifica el formato de salida, por lo que creo que al menos esto debería mencionarse. Consulte la respuesta: stackoverflow.com/a/31552829/952234 que también incluye una nota sobre por qué debería usar gpg en lugar de openssl para esta tarea.
moo
77
No utilice el comando anterior ya que no hay derivación de clave. Lea más aquí: derivación de clave débil openssl
jonasl
También debe especificar una clave o mencionar de dónde proviene. ¿Se fortalece?
Tuntable
2
@jonasl de acuerdo con la última página de manual, dice: "El resumen predeterminado se cambió de MD5 a SHA256 en Openssl 1.1.0". Fuente: github.com/openssl/openssl/blob/master/doc/man1/enc.pod
Kebman el
2
Agregando al comentario de @Kebman, puede agregar -md sha256a su comando de codificación y decodificación si planea usar este archivo en otra máquina. Eso debería cubrirlo contra las incompatibilidades / diferencias de la versión OpenSSL
dev-rowbot
162

Respuesta corta:

Es probable que desee utilizar en gpglugar de opensslver las "Notas adicionales" al final de esta respuesta. Pero para responder la pregunta usando openssl:

Encriptar:

openssl enc -aes-256-cbc -in un_encrypted.data -out encrypted.data

Para descifrar:

openssl enc -d -aes-256-cbc -in encrypted.data -out un_encrypted.data

Nota: Se le solicitará una contraseña cuando cifre o descifre.


Respuesta larga:

Su mejor fuente de información openssl encprobablemente sería: https://www.openssl.org/docs/man1.1.1/man1/enc.html

Línea de comando: openssl enc toma la siguiente forma:

openssl enc -ciphername [-in filename] [-out filename] [-pass arg]
[-e] [-d] [-a/-base64] [-A] [-k password] [-kfile filename] 
[-K key] [-iv IV] [-S salt] [-salt] [-nosalt] [-z] [-md] [-p] [-P] 
[-bufsize number] [-nopad] [-debug] [-none] [-engine id]

Explicación de los parámetros más útiles con respecto a su pregunta:

-e
    Encrypt the input data: this is the default.

-d    
    Decrypt the input data.

-k <password>
    Only use this if you want to pass the password as an argument. 
    Usually you can leave this out and you will be prompted for a 
    password. The password is used to derive the actual key which 
    is used to encrypt your data. Using this parameter is typically
    not considered secure because your password appears in 
    plain-text on the command line and will likely be recorded in 
    bash history.

-kfile <filename>
    Read the password from the first line of <filename> instead of
    from the command line as above.

-a
    base64 process the data. This means that if encryption is taking 
    place the data is base64 encoded after encryption. If decryption 
    is set then the input data is base64 decoded before being 
    decrypted.
    You likely DON'T need to use this. This will likely increase the
    file size for non-text data. Only use this if you need to send 
    data in the form of text format via email etc.

-salt
    To use a salt (randomly generated) when encrypting. You always
    want to use a salt while encrypting. This parameter is actually
    redundant because a salt is used whether you use this or not 
    which is why it was not used in the "Short Answer" above!

-K key    
    The actual key to use: this must be represented as a string
    comprised only of hex digits. If only the key is specified, the
    IV must additionally be specified using the -iv option. When 
    both a key and a password are specified, the key given with the
    -K option will be used and the IV generated from the password 
    will be taken. It probably does not make much sense to specify 
    both key and password.

-iv IV
    The actual IV to use: this must be represented as a string 
    comprised only of hex digits. When only the key is specified 
    using the -K option, the IV must explicitly be defined. When a
    password is being specified using one of the other options, the 
    IV is generated from this password.

-md digest
    Use the specified digest to create the key from the passphrase.
    The default algorithm as of this writing is sha-256. But this 
    has changed over time. It was md5 in the past. So you might want
    to specify this parameter every time to alleviate problems when
    moving your encrypted data from one system to another or when
    updating openssl to a newer version.

Notas adicionales:

Aunque ha preguntado específicamente sobre OpenSSL, es posible que desee considerar el uso de GPG en su lugar con el propósito de cifrado basado en este artículo OpenSSL vs GPG para cifrar copias de seguridad fuera del sitio.

Para usar GPG para hacer lo mismo, usaría los siguientes comandos:

Encriptar:

gpg --output encrypted.data --symmetric --cipher-algo AES256 un_encrypted.data

Para descifrar:

gpg --output un_encrypted.data --decrypt encrypted.data

Nota: Se le solicitará una contraseña cuando cifre o descifre.

mugir
fuente
8
Gran comentario sobre preferir GPG sobre OpenSSL. ¡Me parece increíble que OpenSSL use un hash derivado de contraseña tan débil para la clave!
Mark
2
Asegúrese de utilizar la opción "-md md5" para la compatibilidad con los archivos que se cifraron en openssl anterior sin la opción -md especificada, de lo contrario encontrará que los archivos no se descifrarán en los sistemas más nuevos: github.com/libressl-portable/ portable / issues / 378
Sam Liddicott
1
Los valores predeterminados cambian entre versiones de openssl. 1.0.x usa un valor predeterminado de md5 para la opción -md. La versión 1.1.x usa sha256. Si descifra y obtiene un error ": rutinas de sobres digitales: EVP_DecryptFinal_ex: descifrado incorrecto". intente especificar "-md md5" o "-md sha256".
txyoji
1
"Se le pedirá una contraseña al cifrar o descifrar". gpgme permite descifrar un archivo sin que se me solicite una contraseña. Parece que la contraseña está almacenada durante un período de tiempo, que no quiero.
user76284
1
@moo También parece que la opción --no-symkey-cachedeshabilita el almacenamiento en caché al usar gpg con --symmetric, incluso si el agente se está ejecutando.
user76284
32

Cifrar:

openssl enc -in infile.txt -out encrypted.dat -e -aes256 -k symmetrickey

Descifrar:

openssl enc -in encrypted.dat -out outfile.txt -d -aes256 -k symmetrickey

Para más detalles, ver los openssl(1)documentos.

Ken Cheung
fuente
11
Para usar una contraseña de texto sin formato, reemplácela -k symmetrickeycon -pass stdino-pass 'pass:PASSWORD'
Zenexer
3
No utilice el comando anterior ya que no hay derivación de clave. Lea más aquí: derivación de clave débil openssl
jonasl
44
En relación con el comentario de @jonasl, tenga en cuenta que -k symmetrickeyes engañoso. La -kopción se utiliza para especificar una contraseña, de la cual OpenSSL deriva la clave simétrica. Si desea especificar la clave simétrica, debe usar la -Kopción.
user1071847
13

NO UTILICE OPENSSL DEFAULT KEY DERIVATION.

Actualmente, la respuesta aceptada la utiliza y ya no se recomienda ni es segura.

Es muy factible que un atacante simplemente fuerce la llave con fuerza bruta.

https://www.ietf.org/rfc/rfc2898.txt

PBKDF1 aplica una función hash, que será MD2 [6], MD5 [19] o SHA-1 [18], para derivar claves. La longitud de la clave derivada está limitada por la longitud de la salida de la función hash, que es de 16 octetos para MD2 y MD5 y 20 octetos para SHA-1. PBKDF1 es compatible con el proceso de derivación de claves en PKCS # 5 v1.5. PBKDF1 se recomienda solo por compatibilidad con aplicaciones existentes, ya que las claves que produce pueden no ser lo suficientemente grandes para algunas aplicaciones.

PBKDF2 aplica una función pseudoaleatoria (ver Apéndice B.1 para un ejemplo) para derivar claves. La longitud de la clave derivada es esencialmente ilimitada. (Sin embargo, el espacio de búsqueda efectivo máximo para la clave derivada puede estar limitado por la estructura de la función pseudoaleatoria subyacente. Consulte el Apéndice B.1 para una discusión más detallada). Se recomienda PBKDF2 para nuevas aplicaciones.

Hacer esto:

openssl enc -aes-256-cbc -pbkdf2 -iter 20000 -in hello -out hello.enc -k meow

openssl enc -d -aes-256-cbc -pbkdf2 -iter 20000 -in hello.enc -out hello.out

Nota : Las iteraciones en el descifrado deben ser las mismas que las iteraciones en el cifrado.

Las iteraciones tienen que ser un mínimo de 10000. Aquí hay una buena respuesta sobre la cantidad de iteraciones: https://security.stackexchange.com/a/3993

Además ... tenemos suficiente gente aquí recomendando GPG. Lee la maldita pregunta.

Arnold Balliu
fuente
4

Encriptar:

$ openssl bf < arquivo.txt > arquivo.txt.bf

Para descifrar:

$ openssl bf -d < arquivo.txt.bf > arquivo.txt

bf === Blowfish en modo CBC

fabio almeida
fuente
3

Actualice utilizando una clave pública generada al azar.

Encypt:

openssl enc -aes-256-cbc -a -salt -in {raw data} -out {encrypted data} -pass file:{random key}

Descifrar:

openssl enc -d -aes-256-cbc -in {ciphered data} -out {raw data}

Tengo un tutorial completo sobre esto en http://bigthinkingapplied.com/key-based-encryption-using-openssl/

nneko
fuente
3

Tenga en cuenta que la CLI de OpenSSL utiliza un algoritmo no estándar débil para convertir la frase de contraseña en una clave, y la instalación de resultados de GPG en varios archivos agregados a su directorio de inicio y un proceso de fondo del agente gpg en ejecución. Si desea la máxima portabilidad y control con las herramientas existentes, puede usar PHP o Python para acceder a las API de nivel inferior y pasar directamente una clave AES completa y IV.

Ejemplo de invocación de PHP a través de Bash:

IV='c2FtcGxlLWFlcy1pdjEyMw=='
KEY='Twsn8eh2w2HbVCF5zKArlY+Mv5ZwVyaGlk5QkeoSlmc='
INPUT=123456789023456

ENCRYPTED=$(php -r "print(openssl_encrypt('$INPUT','aes-256-ctr',base64_decode('$KEY'),OPENSSL_ZERO_PADDING,base64_decode('$IV')));")
echo '$ENCRYPTED='$ENCRYPTED
DECRYPTED=$(php -r "print(openssl_decrypt('$ENCRYPTED','aes-256-ctr',base64_decode('$KEY'),OPENSSL_ZERO_PADDING,base64_decode('$IV')));")
echo '$DECRYPTED='$DECRYPTED

Esto produce:

$ENCRYPTED=nzRi252dayEsGXZOTPXW
$DECRYPTED=123456789023456

También puede usar la openssl_pbkdf2función de PHP para convertir una frase de contraseña en una clave de forma segura.

zeroimpl
fuente
La CLI de Openssl ahora implementa y advierte a los usuarios que deben usar PBKDF2 para el hash de contraseñas. Sin embargo, su recuento de iteraciones predeterminado es muy bajo y debe ser mucho mayor.
Anthony
2

Hay un programa de código abierto que encuentro en línea que utiliza openssl para cifrar y descifrar archivos. Lo hace con una sola contraseña. Lo mejor de este script de código abierto es que elimina el archivo original sin cifrar al destruir el archivo. Pero lo peligroso es que una vez que el archivo original no encriptado haya desaparecido, debe asegurarse de recordar su contraseña; de lo contrario, no habrá otra forma de descifrar su archivo.

Aquí el enlace está en github

https://github.com/EgbieAnderson1/linux_file_encryptor/blob/master/file_encrypt.py

Michael linkston
fuente
Las cosas han cambiado cuando se utiliza openssl para el cifrado de archivos, son muchas más opciones, que deben recordarse para que pueda descifrar con éxito los archivos cifrados. Una solución para esto es "keepout" antofthy.gitlab.io/software/#keepout
anthony
2

Como se mencionó en las otras respuestas, las versiones anteriores de openssl usaban una función de derivación de clave débil para derivar una clave de cifrado AES de la contraseña. Sin embargo, openssl v1.1.1 admite una función de derivación de clave más fuerte, donde la clave se deriva de la contraseña utilizandopbkdf2 una sal generada aleatoriamente y múltiples iteraciones de hash sha256 (10,000 por defecto).

Para cifrar un archivo:

 openssl aes-256-cbc -e -salt -pbkdf2 -iter 10000 -in plaintextfilename -out encryptedfilename

Para descifrar un archivo:

  openssl aes-256-cbc -d -salt -pbkdf2 -iter 10000 -in encryptedfilename -out plaintextfilename
mti2935
fuente
Como estas opciones siguen cambiando, significa que también debe mantener un registro de las opciones que se utilizaron al crear cada archivo encriptado openssl. ¡Especialmente porque el recuento de iteraciones debería aumentar con el tiempo! Para una solución, vea como un contenedor relativamente simple alrededor de openssl enc ... "keepout" antofthy.gitlab.io/software/#keepout Se puede expandir para incluir más openssl cuando pasa el tiempo.
Anthony
@anthony parece un proyecto útil. También vea github.com/meixler/web-browser-based-file-encryption-decryption
mti2935
0

Comentarios adicionales a mti2935 buena respuesta.

Parece que a mayor iteración, mejor protección contra la fuerza bruta, y debe usar una iteración alta, ya que puede permitirse el rendimiento / recurso inteligente.

En mi viejo Intel i3-7100 encriptando un archivo bastante grande de 1.5GB:

 time openssl enc -aes256 -e -pbkdf2 -iter 10000 -pass pass:"mypassword" -in "InputFile" -out "OutputFile"
 Seconds: 2,564s

 time openssl enc -aes256 -e -pbkdf2 -iter 262144 -pass pass:"mypassword" -in "InputFile" -out "OutputFile"
 Seconds:  2,775s

Realmente no hay ninguna diferencia, aunque no verifiqué el uso de memoria (?)

Con las GPU de hoy, y las mañanas aún más rápidas, creo que mil millones de iteraciones de fuerza bruta parecen posibles cada segundo.

Hace 12 años, a NVIDIA GeForce 8800 Ultrapodía iterar más de 200,000 millones / seg de iteraciones (aunque el hash MD5)

fuente: Ainane-Barrett-Johnson-Vivar-OpenSSL.pdf

Mr Calvin
fuente