Como usar o OpenSSL para criptografar / descriptografar arquivos?

205

Quero criptografar e descriptografar um arquivo usando uma senha.

Como posso usar o OpenSSL para fazer isso?

aF.
fonte
2
Você deve derivar uma chave e IV da senha usando PKCS5_PBKDF2_HMAC. Você deve usar as EVP_*funções para criptografar e descriptografar. Veja Criptografia e descriptografia simétrica EVP no wiki do OpenSSL. Na verdade, você provavelmente deve estar usando criptografia autenticada porque fornece ambos confidencialidade e autenticidade. Veja Criptografia e descriptografia autenticadas EVP no wiki do OpenSSL.
JWW
3
Não entenda da sua pergunta por que você quer o OpenSSL. Um comentário abaixo mostra que o GPG é melhor - também por causa da segurança. stackoverflow.com/a/31552829/952234 Voto para baixo.
Yaroslav Nikitenko

Respostas:

261

Aviso de segurança : O AES-256-CBC não fornece criptografia autenticada e é vulnerável a ataques oracle padding . Você deve usar algo como a idade .

Criptografar:

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

Descriptografar:

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

Mais detalhes sobre as várias bandeiras

Szocske
fonte
18
A resposta provavelmente não é a ideal (no momento em que escrevo), dependendo do caso de uso do OP. Especificamente, os parâmetros "-a" provavelmente não são ideais e a resposta não explica seu uso. "-a" é normalmente usado quando a saída criptografada deve ser transmitida no formato ASCII / texto e tem o efeito de aumentar o tamanho da saída em comparação com o formato binário. O pôster original não especifica o formato de saída e, portanto, acho que pelo menos isso deve ser mencionado. Consulte a resposta: stackoverflow.com/a/31552829/952234, que também inclui uma observação sobre por que você deve usar gpg em vez de openssl para esta tarefa.
moo
7
Não use o comando acima, pois não há derivação de chave. Leia mais aqui: derivação de chave fraca openssl
jonasl
Também deve especificar uma chave ou mencionar de onde ela vem. Está fortalecido?
Tuntable
2
@jonasl, de acordo com a página de manual mais recente, afirma: “O resumo padrão foi alterado de MD5 para SHA256 no Openssl 1.1.0.” Fonte: github.com/openssl/openssl/blob/master/doc/man1/enc.pod
Kebman
2
Adicionando ao comentário do @Kebman, você pode adicionar -md sha256ao seu comando codificar e decodificar se planeja usar esse arquivo em outra máquina. Isso deve cobri-lo contra OpenSSL versão incompatibilidades / diferenças
dev-rowbot
162

Resposta curta:

Você provavelmente deseja usar em gpgvez de opensslver "Notas adicionais" no final desta resposta. Mas, para responder à pergunta usando openssl:

Para criptografar:

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

Para descriptografar:

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

Nota: Você será solicitado a fornecer uma senha ao criptografar ou descriptografar.


Resposta longa:

Sua melhor fonte de informação para openssl encprovavelmente seria: https://www.openssl.org/docs/man1.1.1/man1/enc.html

Linha de comando: openssl enc assume o seguinte formato:

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]

Explicação dos parâmetros mais úteis em relação à sua pergunta:

-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 Adicionais:

Embora você tenha perguntado especificamente sobre o OpenSSL, considere usar o GPG para fins de criptografia, com base neste artigo OpenSSL vs GPG para criptografar backups externos?

Para usar o GPG para fazer o mesmo, você usaria os seguintes comandos:

Para criptografar:

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

Para descriptografar:

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

Nota: Você será solicitado a fornecer uma senha ao criptografar ou descriptografar.

moo
fonte
8
Ótimo comentário sobre como preferir o GPG ao OpenSSL. Acho incrível que o OpenSSL use um hash derivado de senha tão fraco para a chave!
Mark
2
Certifique-se de usar a opção "-md md5" para compatibilidade com arquivos criptografados em openssl antigo sem a opção -md especificada, caso contrário, você descobrirá que os arquivos não serão descriptografados em sistemas mais novos: github.com/libressl-portable/ questões portáteis / / 378
Sam Liddicott
1
Os valores padrão são alterados entre as versões do openssl. 1.0.x usa um padrão de md5 para a opção -md. A versão 1.1.x usa sha256. Se você descriptografar e obter um erro ": rotinas de envelope digital: EVP_DecryptFinal_ex: descriptografia incorreta". tente especificar "-md md5" ou "-md sha256".
txyoji
1
"Você será solicitado a fornecer uma senha ao criptografar ou descriptografar." gpgestá me permitindo descriptografar um arquivo sem ser solicitada uma senha. Parece que a senha está armazenada por algum período de tempo, o que eu não quero.
user76284
1
@moo Parece também que a opção --no-symkey-cachedesativa o cache ao usar o gpg --symmetric, mesmo que o agente esteja em execução.
user76284
32

Criptografar:

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

Descriptografar:

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

Para detalhes, consulte os openssl(1)documentos.

Ken Cheung
fonte
11
Para usar uma senha de texto sem formatação, substitua -k symmetrickeypor -pass stdinou-pass 'pass:PASSWORD'
Zenexer 14/02
3
Não use o comando acima, pois não há derivação de chave. Leia mais aqui: derivação de chave fraca openssl
jonasl
4
Relacionado ao comentário de @ jonasl, observe que isso -k symmetrickeyé enganador. A -kopção é usada para especificar uma senha, da qual o OpenSSL deriva a chave simétrica. Se você deseja especificar a chave simétrica, deve usar a -Kopção
user1071847
13

NÃO USE DERIVAÇÃO DE CHAVE PADRÃO OPENSSL.

Atualmente, a resposta aceita faz uso dela e não é mais recomendada e segura.

É muito viável para um invasor simplesmente forçar a chave com força bruta.

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

PBKDF1 aplica uma função de hash, que deve ser MD2 [6], MD5 [19] ou SHA-1 [18], para derivar chaves. O comprimento da chave derivada é limitado pelo comprimento da saída da função hash, que é 16 octetos para MD2 e MD5 e 20 octetos para SHA-1. PBKDF1 é compatível com o processo de derivação de chave no PKCS # 5 v1.5. O PBKDF1 é recomendado apenas para compatibilidade com aplicativos existentes, pois as chaves produzidas podem não ser grandes o suficiente para alguns aplicativos.

PBKDF2 aplica uma função pseudo-aleatória (consulte o Apêndice B.1 para obter um exemplo) para derivar chaves. O comprimento da chave derivada é essencialmente ilimitado. (No entanto, o espaço máximo efetivo de pesquisa para a chave derivada pode ser limitado pela estrutura da função pseudoaleatória subjacente. Consulte o Apêndice B.1 para obter mais discussões.) O PBKDF2 é recomendado para novas aplicações.

Faça isso:

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 : As iterações em descriptografia precisam ser as mesmas que as iterações na criptografia.

As iterações devem ter no mínimo 10000. Aqui está uma boa resposta sobre o número de iterações: https://security.stackexchange.com/a/3993

Além disso ... temos pessoas suficientes aqui recomendando GPG. Leia a maldita pergunta.

Arnold Balliu
fonte
4

Para criptografar:

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

Para descriptografar:

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

bf === Blowfish no modo CBC

fabio almeida
fonte
3

Atualize usando uma chave pública gerada aleatoriamente.

Codificar:

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

Descriptografar:

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

Eu tenho um tutorial completo sobre isso em http://bigthinkingapplied.com/key-based-encryption-using-openssl/

nneko
fonte
3

Observe que a CLI do OpenSSL usa um algoritmo não padrão fraco para converter a senha em uma chave e a instalação do GPG resulta em vários arquivos adicionados ao diretório inicial e em execução em processo de segundo plano do agente gpg. Se você deseja portabilidade e controle máximos com as ferramentas existentes, pode usar PHP ou Python para acessar as APIs de nível inferior e passar diretamente uma chave AES e IV completa.

Exemplo de invocação do PHP via 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

Isso gera:

$ENCRYPTED=nzRi252dayEsGXZOTPXW
$DECRYPTED=123456789023456

Você também pode usar a openssl_pbkdf2função do PHP para converter uma senha em uma chave com segurança.

zeroimpl
fonte
O Openssl CLI agora implementa e avisa os usuários que eles devem usar PBKDF2 para hash de senha. No entanto, sua contagem de iterações padrão é muito baixa e precisa ser muito maior.
anthony
2

Existe um programa de código aberto que eu acho on-line, que usa o openssl para criptografar e descriptografar arquivos. Faz isso com uma única senha. A grande vantagem desse script de código aberto é que ele exclui o arquivo não criptografado original, destruindo-o. Mas o mais perigoso é que, uma vez que o arquivo original não criptografado se foi, você deve se lembrar da senha, caso contrário, não haverá outra maneira de descriptografar o arquivo.

Aqui o link está no github

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

Michael linkston
fonte
As coisas mudaram ao usar o openssl para criptografia de arquivos, são muito mais opções, que precisam ser lembradas para que você possa descriptografar com êxito os arquivos criptografados. Uma solução para isso é "keepout" antofthy.gitlab.io/software/#keepout
anthony
2

Conforme mencionado nas outras respostas, as versões anteriores do openssl usavam uma função de derivação de chave fraca para derivar uma chave de criptografia AES da senha. No entanto, o openssl v1.1.1 suporta uma função de derivação de chave mais forte, na qual a chave é derivada da senha usando pbkdf2um sal gerado aleatoriamente e várias iterações de sha256 hashing (10.000 por padrão).

Para criptografar um arquivo:

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

Para descriptografar um arquivo:

  openssl aes-256-cbc -d -salt -pbkdf2 -iter 10000 -in encryptedfilename -out plaintextfilename
mti2935
fonte
O que, como essas opções continuam mudando, significa que você também precisa manter um registro de quais opções foram usadas ao criar cada arquivo criptografado openssl. Especialmente porque a contagem de iterações deve aumentar com o tempo! Para uma solução, veja como um invólucro relativamente simples em torno do openssl enc ... "keepout" antofthy.gitlab.io/software/#keepout Ele pode ser expandido para incluir mais openssl com o passar do tempo.
anthony
@anthony parece um projeto útil. Consulte também github.com/meixler/web-browser-based-file-encryption-decryption
mti2935
0

Comentários adicionais para mti2935 boa resposta.

Parece que, na iteração mais alta, melhor proteção contra a força bruta e você deve usar uma iteração alta, pois pode oferecer desempenho / recursos.

No meu antigo Intel i3-7100, criptografando um arquivo bastante grande de 1,5 GB:

 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

Não há realmente nenhuma diferença, embora não tenha verificado o uso da memória (?)

Com as GPUs de hoje e amanhã mais rápidos, acho que bilhões de iterações de força bruta parecem possíveis a cada segundo.

12 anos, era NVIDIA GeForce 8800 Ultrapossível iterar mais de 200.000 milhões / s de iterações (embora o hash MD5)

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

MrCalvin
fonte