如何使用公钥加密openssl中的大文件

Posted

技术标签:

【中文标题】如何使用公钥加密openssl中的大文件【英文标题】:How to encrypt a large file in openssl using public key 【发布时间】:2011-10-31 21:25:29 【问题描述】:

我怎样才能用公钥加密一个大文件,这样除了拥有私钥的人之外,其他人都无法解密它?

我可以制作 RSA 公钥和私钥,但在使用此命令加密大文件时:

openssl rsautl -encrypt -pubin -inkey public.pem -in myLargeFile.xml -out myLargeFile_encrypted.xml

以及我如何也可以执行解密....

我通过以下命令创建我的私钥和公钥

openssl genrsa -out private.pem 1024
openssl rsa -in private.pem -out public.pem -outform PEM -pubout

我收到此错误:

RSA operation error
3020:error:0406D06E:rsa routines:RSA_padding_add_PKCS1_type_2:data too large for key size:.\crypto\rsa\rsa_pk1.c:151:

我尝试制作大小从 1024 到 1200 位的密钥,但没有运气,同样的错误

【问题讨论】:

【参考方案1】:

公钥加密不适用于加密任意长的文件。一个使用对称密码(比如 AES)进行正常加密。每次生成、使用新的随机对称密钥,然后使用 RSA 密码(公钥)进行加密。密文与加密的对称密钥一起被传送给接收者。接收方使用自己的私钥解密对称密钥,然后使用对称密钥解密消息。

私钥永远不会共享,只有公钥用于加密随机对称密码。

【讨论】:

但是非对称加密的重点是防止共享私人秘密,这种方法会导致共享密钥,即使它是用非对称加密加密的。使用像 RSA 这样的非对称加密来加密有什么优势吗?共享密钥与对称算法 @techno:你没有分享任何秘密。您生成一次性随机密钥,使用它来加密单个消息,然后将其丢弃。您随消息发送的密钥仅对该消息有效。 是的,但是特定消息的一次性密钥是共享的,对吗?使用 RSA 等非对称加密技术来加密共享密钥与对称算法相比有什么优势 是的。您还共享消息本身。如果您害怕共享密钥,也不要共享消息。 @n.m. “公钥加密不用于加密任意长的文件。”,严格从性能的角度来看?使用 recipient(或应该读取文件的任何人)的公钥对整个文件进行 RSA 加密会带来其他缺点吗?【参考方案2】:

在 OpenSSL 和命令行中安全和高度安全地编码任何文件的解决方案:

您应该准备好一些 X.509 证书来加密 PEM 格式的文件。

加密文件:

openssl smime -encrypt -binary -aes-256-cbc -in plainfile.zip -out encrypted.zip.enc -outform DER yourSslCertificate.pem

什么是什么:

smime - 用于 S/MIME 实用程序的 ssl 命令 (smime(1)) -encrypt - 选择的文件处理方法 -binary - 使用安全文件处理。通常,输入消息会按照 S/MIME 规范的要求转换为“规范”格式,此开关禁用它。所有二进制文件(如图像、声音、ZIP 档案)都需要它。 -aes-256-cbc - 选择 256 位密码 AES 进行加密(强)。如果未指定,则使用 40 位 RC2(非常弱)。 (Supported ciphers) -in plainfile.zip - 输入文件名 -out encrypted.zip.enc - 输出文件名 -outform DER - 将输出文件编码为二进制。如果不指定,文件采用base64编码,文件大小增加30%。 yourSslCertificate.pem - 证书的文件名。应该是 PEM 格式。

该命令可以非常有效地对大文件进行强加密,无论其格式如何。已知问题: 当您尝试加密大文件 (>600MB) 时发生错误。没有错误抛出,但加密文件将被损坏。始终验证每个文件! (或使用 PGP - 对使用公钥的文件加密有更大的支持)

解密文件:

openssl smime -decrypt -binary -in encrypted.zip.enc -inform DER -out decrypted.zip -inkey private.key -passin pass:your_password

什么是什么:

-inform DER - 与上面的 -outform 相同 -inkey private.key - 你的私钥的文件名。应该是 PEM 格式,并且可以通过密码加密。 -passin pass:your_password - 你的私钥加密密码。 (passphrase arguments)

【讨论】:

当我执行上面的命令时,我会得到一个带有所有 smime 选项的 Usage smime [options] yourSslCertificate.pem ... 原来我必须做 -aes256 而不是 -aes-256-cbc “该命令可以非常有效地加密任何文件,无论其大小或格式如何。”,但是在最后一段你承认它根本无法加密大文件......也许你应该当您的解决方案最终不适用于大文件时,不要对最终解决方案和所有文件做出如此自大的主张。您应该从解决方案的限制和范围开始,而不是结束。 是否有关于大于 600MB 文件的已知问题的错误报告?如果您只有可用的公钥,则无法验证加密文件。 我无法使用 public 密钥(如问题所要求的那样)使其工作。它需要证书。【参考方案3】:

我发现http://www.czeskis.com/random/openssl-encrypt-file.html 的说明很有用。

用您的示例中的文件名解释链接的站点:

生成对称密钥,因为您可以用它加密大文件

openssl rand -base64 32 > key.bin

使用对称密钥加密大文件

openssl enc -aes-256-cbc -salt -in myLargeFile.xml \
  -out myLargeFile.xml.enc -pass file:./key.bin

加密对称密钥,以便您可以安全地将其发送给对方 人

openssl rsautl -encrypt -inkey public.pem -pubin -in key.bin -out key.bin.enc

销毁未加密的对称密钥,以免无人发现

shred -u key.bin

此时,您发送加密的对称密钥 (key.bin.enc) 和加密的大文件(myLargeFile.xml.enc)到另一个 人

然后其他人可以使用他们的私钥解密对称密钥 键使用

openssl rsautl -decrypt -inkey private.pem -in key.bin.enc -out key.bin

现在他们可以使用对称密钥来解密文件

openssl enc -d -aes-256-cbc -in myLargeFile.xml.enc \
  -out myLargeFile.xml -pass file:./key.bin

你就完成了。其他人拥有解密文件,并且已安全发送。

【讨论】:

这是最好的解决方案。应该是排名靠前且被接受的答案【参考方案4】:

您不能使用rsautl 直接加密大文件。相反,请执行以下操作:

    使用openssl rand 生成密钥,例如。 openssl rand 32 -out keyfile 使用openssl rsautl加密密钥文件 使用openssl enc 加密数据,使用步骤 1 中生成的密钥。 将加密密钥文件与加密数据打包在一起。接收者需要使用他们的私钥解密密钥,然后使用生成的密钥解密数据。

【讨论】:

【参考方案5】:

不建议使用 smime 加密非常大的文件,因为您可以使用 -stream 选项加密大文件,但由于硬件限制see: problem decrypting big files

而无法解密生成的文件

如上所述,公钥加密不适用于加密任意长的文件。因此,以下命令将生成密码短语,使用对称加密加密文件,然后使用非对称(公钥)加密密码短语。注意:smime 包括使用主公钥和备用密钥来加密密码短语。备份公钥/私钥对将是谨慎的。

随机密码生成

将 RANDFILE 值设置为当前用户可访问的文件,生成 passwd.txt 文件并清理设置

export OLD_RANDFILE=$RANDFILE
RANDFILE=~/rand1
openssl rand -base64 2048 > passwd.txt
rm ~/rand1
export RANDFILE=$OLD_RANDFILE

加密

使用以下命令加密文件,使用 passwd.txt 内容作为密码和 AES256 到 base64(-a 选项)文件。使用非对称加密将 passwd.txt 加密到文件 XXLarge.crypt.pass 中,使用主公钥和备用密钥。

openssl enc -aes-256-cbc -a -salt -in XXLarge.data -out XXLarge.crypt -pass file:passwd.txt
openssl smime -encrypt -binary -in passwd.txt -out XXLarge.crypt.pass -aes256 PublicKey1.pem PublicBackupKey.pem
rm passwd.txt

解密

解密只是将 XXLarge.crypt.pass 解密为 passwd.tmp,将 XXLarge.crypt 解密为 XXLarge2.data,然后删除 passwd.tmp 文件。

openssl smime -decrypt -binary -in XXLarge.crypt.pass -out passwd.tmp -aes256 -recip PublicKey1.pem -inkey PublicKey1.key
openssl enc -d -aes-256-cbc -a -in XXLarge.crypt -out XXLarge2.data -pass file:passwd.tmp
rm passwd.tmp

已针对 >5GB 文件进行了测试..

5365295400 Nov 17 10:07 XXLarge.data
7265504220 Nov 17 10:03 XXLarge.crypt
      5673 Nov 17 10:03 XXLarge.crypt.pass
5365295400 Nov 17 10:07 XXLarge2.data

【讨论】:

只是我的两分钱:我会放弃 -a 以保持加密文件大小更小(无 Base64 编码)并添加 -pbkdf2 以获得更好的密钥派生(2021 年 openssl enc 抱怨关于简单-pass) smime 不是已经用对称密码加密,然后用 RSA 加密密钥吗?单独加密是否只是 smime 子命令对大文件无法正常工作的一种解决方法?【参考方案6】:

更多解释n. 'pronouns' m.的回答,

公钥加密不适用于加密任意长的文件。一 使用对称密码(比如 AES)进行正常加密。每个 生成、使用和加密新的随机对称密钥的时间 使用 RSA 密码(公钥)。密文连同 加密的对称密钥被传输给接收者。收件人 使用他的私钥解密对称密钥,然后使用 用于解密消息的对称密钥。

加密的流程:

+---------------------+      +--------------------+
|                     |      |                    |
| generate random key |      |   the large file   |
|        (R)          |      |        (F)         |
|                     |      |                    |
+--------+--------+---+      +----------+---------+
         |        |                     |
         |        +------------------+  |
         |                           |  |
         v                           v  v
+--------+------------+     +--------+--+------------+
|                     |     |                        |
| encrypt (R) with    |     | encrypt (F)            |
| your RSA public key |     | with symmetric key (R) |
|                     |     |                        |
|  ASym(PublicKey, R) |     |     EF = Sym(F, R)     |
|                     |     |                        |
+----------+----------+     +------------+-----------+
           |                             |
           +------------+ +--------------+
                        | |
                        v v
         +--------------+-+---------------+
         |                                |
         |   send this files to the peer  |
         |                                |
         |     ASym(PublicKey, R) + EF    |
         |                                |
         +--------------------------------+

以及解密流程

   +----------------+        +--------------------+
   |                |        |                    |
   | EF = Sym(F, R) |        | ASym(PublicKey, R) |
   |                |        |                    |
   +-----+----------+        +---------+----------+
         |                             |
         |                             |
         |                             v
         |   +-------------------------+-----------------+
         |   |                                           |
         |   |             restore key (R)               |
         |   |                                           |
         |   | R <= ASym(PrivateKey, ASym(PublicKey, R)) |
         |   |                                           |
         |   +---------------------+---------------------+
         |                         |
         v                         v
     +---+-------------------------+---+
     |                                 |
     |       restore the file (F)      |
     |                                 |
     |      F <= Sym(Sym(F, R), R)     |
     |                                 |
     +---------------------------------+

此外,您还可以使用以下命令:

# generate random symmetric key
openssl rand -base64 32 > /config/key.bin

# encryption
openssl rsautl -encrypt -pubin -inkey /config/public_key.pem -in /config/key.bin -out /config/key.bin.enc
openssl aes-256-cbc -a -pbkdf2 -salt -in  $file_name -out $file_name.enc -kfile /config/key.bin

# now you can send these files: $file_name.enc + /config/key.bin.enc

# decryption
openssl rsautl -decrypt -inkey /config/private_key.pem -in /config/key.bin.enc -out /config/key.bin
openssl aes-256-cbc -d -a -pbkdf2 -in $file_name.enc -out $file_name -kfile /config/key.bin

【讨论】:

最好使用-kfile /config/key.bin 而不是-k $(cat /config/key.bin),否则密码会在进程列表(任务管理器)中泄漏。【参考方案7】:

要使用openssl smime 安全地加密大文件 (>600MB),您必须将每个文件分成小块:

# Splits large file into 500MB pieces
split -b 500M -d -a 4 INPUT_FILE_NAME input.part.

# Encrypts each piece
find -maxdepth 1 -type f -name 'input.part.*' | sort | xargs -I % openssl smime -encrypt -binary -aes-256-cbc -in % -out %.enc -outform DER PUBLIC_PEM_FILE

为方便起见,以下是如何解密并将所有部分放在一起:

# Decrypts each piece
find -maxdepth 1 -type f -name 'input.part.*.enc' | sort | xargs -I % openssl smime -decrypt -in % -binary -inform DEM -inkey PRIVATE_PEM_FILE -out %.dec

# Puts all together again
find -maxdepth 1 -type f -name 'input.part.*.dec' | sort | xargs cat > RESTORED_FILE_NAME

【讨论】:

【参考方案8】:

也许您应该查看这个 (How to encrypt data in php using Public/Private keys?) 问题的已接受答案。

它展示了如何使用 OpenSSL 的 S/mime 功能来做同样的事情而不需要手动处理对称密钥,而不是手动解决 RSA 的消息大小限制(或者可能是一个特征)。

【讨论】:

以上是关于如何使用公钥加密openssl中的大文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 openssl 创建公钥和私钥?

如何从 .cer 中提取 RSA 公钥并使用 OpenSSL 将其存储在 .pem 中?

openssl rsa 可以用私钥加密 公钥解密吗

求助,在android端使用openssl生成的rsapublicKey解密的相关问题

安全不安全001:openssl生成非对称加密RSA公钥密钥命令

如何解密 .NET 中的 RSA 内容?