我想用一个密码加密和解密一个文件。

我如何使用OpenSSL来做到这一点?


当前回答

注意,OpenSSL CLI使用弱非标准算法将密码码转换为密钥,安装GPG会导致添加到主目录的各种文件,并运行GPG -agent后台进程。如果您希望最大限度地利用现有工具进行可移植性和控制,您可以使用PHP或Python来访问底层api,并直接传入完整的AES Key和IV。

示例PHP调用通过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

这个输出:

$ENCRYPTED=nzRi252dayEsGXZOTPXW
$DECRYPTED=123456789023456

您还可以使用PHP的openssl_pbkdf2函数安全地将密码短语转换为密钥。

其他回答

安全警告:AES-256-CBC不提供经过身份验证的加密,容易受到填充oracle攻击。你应该用年龄之类的词来代替。

加密:

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

解密:

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

关于各种标志的更多细节

更好的选择:GPG

虽然您特别询问了OpenSSL,但基于本文,您可能希望考虑使用GPG来代替加密OpenSSL vs GPG用于加密场外备份?

要使用GPG来做同样的事情,您可以使用以下命令:

加密:

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

解密:

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

注意:加密或解密时会提示输入密码。使用——no-symkey-cache标志表示没有缓存。


回复:OpenSSL -简短回答

您可能希望使用gpg而不是openssl,因此请参阅答案末尾的“附加说明”。但是要用openssl来回答这个问题:

加密:

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

解密:

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

注意:加密或解密时会提示输入密码。


回复:OpenSSL -长答案

关于openssl enc最好的信息来源可能是:https://www.openssl.org/docs/man1.1.1/man1/enc.html

命令行: Openssl enc采用以下形式:

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]

关于你的问题最有用的参数解释:

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

不要使用openssl默认密钥派生。

目前公认的答案使用它,它不再被推荐和安全。

对于攻击者来说,简单地暴力破解密钥是非常可行的。

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

PBKDF1 applies a hash function, which shall be MD2 [6], MD5 [19] or SHA-1 [18], to derive keys. The length of the derived key is bounded by the length of the hash function output, which is 16 octets for MD2 and MD5 and 20 octets for SHA-1. PBKDF1 is compatible with the key derivation process in PKCS #5 v1.5. PBKDF1 is recommended only for compatibility with existing applications since the keys it produces may not be large enough for some applications. PBKDF2 applies a pseudorandom function (see Appendix B.1 for an example) to derive keys. The length of the derived key is essentially unbounded. (However, the maximum effective search space for the derived key may be limited by the structure of the underlying pseudorandom function. See Appendix B.1 for further discussion.) PBKDF2 is recommended for new applications.

这样做:

Openssl enc -aes-256-cbc -pbkdf2 -iter 20000 -in hello -out hello。Enc -k喵

Openssl enc -d -aes-256-cbc -pbkdf2 -iter 20000 - hello。出来你好,出来

注意:解密中的迭代必须与加密中的迭代相同。

迭代最少要达到10000次。 这里有一个关于迭代次数的很好的答案:https://security.stackexchange.com/a/3993

也……推荐GPG的人已经够多了。读那该死的问题。

加密:

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

解密:

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

详细信息请参见openssl(1)文档。

正如在其他回答中提到的,openssl的以前版本使用弱密钥派生函数从密码派生AES加密密钥。但是,openssl v1.1.1支持更强的密钥派生函数,其中密钥是使用pbkdf2和随机生成的salt以及多次sha256哈希迭代(默认为10,000)从密码派生的。

加密文件:

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

解密文件:

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

注意:在javascript中(使用web crypto api)可以在https://github.com/meixler/web-browser-based-file-encryption-decryption上找到等效/兼容的实现。