如何使用OpenSSL加密/解密文件?

How to use OpenSSL to encrypt/decrypt files?

提问人:aF. 提问时间:4/17/2013 最后编辑:Matthias BraunaF. 更新时间:6/16/2023 访问量:769957

问:

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

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

加密 OpenSSL

评论

3赞 jww 5/16/2015
您应该使用 从密码中派生 Key 和 IV。您应该使用这些函数进行加密和解密。请参阅 OpenSSL wiki 上的 EVP 对称加密和解密。事实上,您可能应该使用经过身份验证的加密,因为它同时提供了机密性和真实性。请参阅 OpenSSL wiki 上的 EVP Authenticated Encryption and DecryptionPKCS5_PBKDF2_HMACEVP_*
3赞 Yaroslav Nikitenko 3/9/2016
从你的问题中不明白你为什么需要OpenSSL。下面的评论显示 GPG 更好 - 也是因为安全性。stackoverflow.com/a/31552829/952234我投了反对票。
0赞 anthony 9/23/2020
您可能想查看“keepout”,以便保存与加密文件一起使用的所有加密选项......这一点尤其重要,因为 openssl enc 的“默认”选项已经改变,并且将来可能会改变。还为新的 -pbkdf2 选项设置更高的随机迭代计数。antofthy.gitlab.io/software/#keepout
0赞 hasti.au 11/24/2023
我不能用这些代码解密,有什么可以帮助我解密我的文件吗?@matthias Braun

答:

349赞 Szocske 4/17/2013 #1

安全警告:AES-256-CBC 不提供经过身份验证的加密,容易受到填充预言机攻击。您应该改用年龄之类的东西。

加密:

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

有关各种标志的更多详细信息

评论

37赞 moo 3/27/2016
答案可能不是最佳的(在撰写本文时),具体取决于 OP 的用例。具体来说,参数“-a”可能不是最优的,答案没有解释它的用法。当加密输出以 ASCII/文本形式传输时,通常使用“-a”,与二进制形式相比,具有增加输出大小的效果。原始海报没有指定输出格式,所以我觉得至少应该提到这一点。请参阅答案:stackoverflow.com/a/31552829/952234 其中还包括关于为什么应该使用 gpg 而不是 openssl 来完成此任务的注释。
12赞 Jonas Lejon 4/29/2016
不要使用上述命令,因为没有密钥派生。在这里阅读更多: openssl 弱密钥派生
1赞 Tuntable 5/9/2016
还应该指定一个密钥,或提及它的来源。它加强了吗?
6赞 Kebman 7/5/2018
@jonasl根据最新的手册页,它指出:“在 Openssl 1.1.0 中,默认摘要已从 MD5 更改为 SHA256。来源: github.com/openssl/openssl/blob/master/doc/man1/enc.pod
4赞 dev-rowbot 10/1/2018
除了 @Kebman 的注释之外,如果您计划在另一台计算机上使用此文件,则可以添加到编码和解码命令中。这应该可以防止OpenSSL版本不兼容/差异-md sha256
50赞 Ken Cheung 4/17/2013 #2

加密:

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) 文档。

评论

17赞 Zenexer 2/14/2015
若要使用纯文本密码,请替换为 或-k symmetrickey-pass stdin-pass 'pass:PASSWORD'
6赞 Jonas Lejon 4/29/2016
不要使用上述命令,因为没有密钥派生。在这里阅读更多: openssl 弱密钥派生
8赞 user1071847 8/23/2017
与@jonasl的评论相关,请注意这是误导性的。该选项用于指定密码,OpenSSL 从中派生对称密钥。如果要指定对称密钥,则必须使用该选项。-k symmetrickey-k-K
0赞 hasti.au 11/24/2023
@Andrii 阿布拉莫夫 我无法用这些代码解密,有没有可以帮助我和解密我的文件?
8赞 nneko 8/22/2014 #3

使用随机生成的公钥进行更新。

Encypt:

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

解密:

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

评论

0赞 Ewoks 12/2/2020
如果该页面仍然在线并且使用 https,那就更好了
3赞 Michael linkston 12/2/2014 #4

我在网上找到了一个开源程序,它使用 openssl 来加密和解密文件。它使用单个密码执行此操作。这个开源脚本的伟大之处在于它通过粉碎文件来删除原始未加密的文件。但危险的是,一旦原始未加密的文件消失了,您必须确保记住密码,否则它们就无法解密您的文件。

这里是github上的链接

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

评论

0赞 anthony 5/27/2020
使用 openssl 进行文件加密时情况发生了变化,有更多的选项,需要记住这些选项,以便您可以成功解密加密文件。一个解决方案是“保持”antofthy.gitlab.io/software/#keepout
266赞 moo 7/22/2015 #5

使用 GPG(OpenSSL 的更好替代品)

尽管您已经特别询问了 OpenSSL(有关 OpenSSL 解决方案,请参阅下面的“使用 OpenSSL”),但您可能要考虑使用 GPG 来代替加密,基于本文 OpenSSL 与 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(长答案)

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

命令行:采用以下形式: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.

评论

16赞 Mark 10/26/2016
关于更喜欢 GPG 而不是 OpenSSL 的好评论。我发现 OpenSSL 使用如此弱的密码派生哈希作为密钥,这真是令人难以置信!
5赞 Sam Liddicott 7/18/2018
请务必使用“-md md5”选项,以便与在未指定 -md 选项的旧 openssl 上加密的文件兼容,否则您会发现文件在较新的系统上无法解密: github.com/libressl-portable/portable/issues/378
11赞 user76284 7/30/2019
“加密或解密时,系统将提示您输入密码。” 让我在不提示输入密码的情况下解密文件。看起来密码存储了一段时间,这是我不想要的。gpg
3赞 moo 8/1/2019
@user76284 这可能会解决您的问题:unix.stackexchange.com/a/395876/79875 。我想你已经跑了gpg-agent
4赞 user76284 8/1/2019
@moo 当将 gpg 与 一起使用时,该选项似乎也会禁用缓存,即使代理正在运行也是如此。--no-symkey-cache--symmetric
8赞 Fábio Almeida 8/1/2015 #6

要加密:

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

解密:

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

bf === CBC 模式下的河豚

评论

0赞 velcrow 3/24/2023
这在 openssl 3 中不起作用,是写的。
2赞 zeroimpl 2/8/2017 #7

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

通过 Bash 调用的 PHP 示例:

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

评论

0赞 anthony 5/27/2020
Openssl CLI 现在实现并警告用户他们应该使用 PBKDF2 进行密码哈希。但是,它的默认迭代计数非常低,并且需要大得多。
28赞 Arnold Balliu 5/4/2019 #8

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

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

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

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

PBKDF1 应用哈希函数,该函数应为 MD2 [6]、MD5 [19] 或 SHA-1 [18],用于派生密钥。派生键的长度是有界的 哈希函数输出的长度,MD2 为 16 个八位字节 以及 SHA-1 的 MD5 和 20 个八位字节。PBKDF1 与密钥兼容 PKCS #5 v1.5 中的派生过程。建议仅将 PBKDF1 用于与现有 应用程序,因为它生成的密钥可能不够大 一些应用程序。

PBKDF2 应用伪随机函数(参见附录 B.1 example) 派生密钥。派生密钥的长度实质上是 无限。(但是,派生密钥的最大有效搜索空间可能受到底层结构的限制 伪随机函数。有关进一步讨论,请参阅附录 B.1。 PBKDF2 推荐用于新应用。

这样做:

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

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

迭代次数必须至少为 10000 次。 以下是关于迭代次数的一个很好的答案:https://security.stackexchange.com/a/3993

也。。。我们这里有足够多的人推荐 GPG。阅读该死的问题。

评论

0赞 anthony 9/23/2020
注意:PBKDF2 现在是 openssl enc 的一部分(最终)。但是,迭代计数非常低,需要设置为更高的级别。如果该计数是随机的,那么您的加密也会获得额外的“咸味”。
0赞 oᴉɹǝɥɔ 2/4/2022
链接的文章很棒。它还暗示,与其选择线性增加计算资源的高计数,不如简单地使用具有高熵的强密码,导致计算复杂性呈指数级增长。每增加 10 位熵相当于将 iter 计数乘以 1000。例如,如果您有 >28 个随机字符(来自 62 个字符)作为密码,则完全无需担心迭代计数。
0赞 Andrew S 5/30/2023
如果在这两个语句下面定义了所有使用的开关和命令,那将是非常有益的。
0赞 Andrew S 5/30/2023
什么是 -k?它不在手册页中。
0赞 Jon V 9/15/2023
@AndrewS - 第一行:用作“Cypher 命令”,是“基于密码的密钥派生函数,第 2 代”,是密钥派生函数运行的迭代次数,输入文件,加密/解密的结果,字面意思是使用的密码。第二个命令将提示输入密码,在本例中为密码。为了您的缘故,请使用比;)长得多的密码。注意:我通常使用并且通常是一个 64+ 字符的文件。您将需要它来解密,所以不要丢失它!aes-256-cbc-pbkdf2-iter-in-out-kmeowmeow-pass file:keyfilekeyfile
15赞 mti2935 4/12/2020 #9

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

要加密文件:

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 加密 api)可以在 https://github.com/meixler/web-browser-based-file-encryption-decryption 中找到。

评论

0赞 anthony 5/27/2020
由于这些选项不断变化,这意味着您还需要记录在创建每个 openssl 加密文件时使用了哪些选项。特别是因为迭代次数应该随着时间的推移而增加!对于一个解决方案,请参阅相对简单的 openssl enc 包装器...“keepout” antofthy.gitlab.io/software/#keepout 随着时间的推移,它可以扩展到包括更多的openssl。
0赞 Andrew S 5/30/2023
你需要解释所有这些开关,没有它,它只是没有提供理解的魔术代码。
1赞 Jon V 9/15/2023
@AndrewS同意 - openssl 手册页并不像大多数其他页面那么好。您需要知道,您必须查看有关使用.man encopenssl enc