使用openssl smime 命令加密数据会以这样一种方式对其进行加密,以便收件人using email 可以接收和解密。这意味着它使用代表各种实体(发送者、接收者)并包含与这些实体唯一关联的密钥的证书来对包含的数据进行签名、加密、解密和验证签名。
正如 Artjom 在他们的评论中指出的那样,使用了混合密码系统。这意味着使用symmetric 和asymmetric 加密算法的组合,因为它们各有优缺点。与非对称加密(如 RSA)相比,对称加密(如 AES)速度极快。但是,AES/CBC 仅提供机密性,不提供完整性、身份验证或不可否认性。非对称加密可以提供完整性、身份验证和不可否认性。非对称加密对它可以加密的数据量也有相当低的限制(例如,一个 RSA-4096 位密钥一次最多可以加密 446 个字节)。通过结合这两种方法,我们可以发挥各自的优势并减轻对方的弱点。
在这种情况下,让我们的消息是M。生成长度为 256 位的 AES/CBC 密钥 Kaes 并用于加密原始数据,使得密文 C 为 C = E(Kaes, M)。然后使用接收者的公钥Krpub 将Kaes 加密为C' = E(Krpub, Kaes)。加密这少量数据的成本相对较低,即使我们使用的是昂贵的操作。
注意 在加密临时会话密钥之前,可能会使用发件人的私钥 Kspriv 对其进行签名,除非数字签名被禁用。我不是 100% 确定 S/MIME,但这就是 PGP 的工作方式,因为当发送给多个收件人时,使用n 收件人的公钥加密会话密钥然后用发件人的私钥 O(2n) 与 O(n+1) (不是真正的 Big-O 表示法,但对于传达这一点很有效)。无论接收者如何,会话密钥的签名都是相同的,因为它仅取决于发送者的私钥。
现在剩下的就是连接加密的会话密钥C' 和密文C 并将它们传输给接收者。在真实的 S/MIME 消息中,还会传输有关发送者公钥的识别信息,以便于签名验证。接收者解析完整的加密消息,使用接收者的私钥Krpriv解密会话密钥,然后使用会话密钥Kaes解密密文C。
但是,对于您的情况,所有这些似乎都有些过头了。如果您不需要与电子邮件通信系统集成而只是尝试加密大文件以进行存储,openssl 还提供了一个简单的enc 命令。您可以按如下方式使用它:
基于密码的加密:
$ openssl enc -aes-256-cbc -in large_plain_file.dmg -out large_encrypted_file.enc -k thisIsABadPassword
-k 允许您在从中派生密钥的命令行上输入密码。 OpenSSL 使用确定性密钥派生函数 (KDF)(实际上是 key, iv = MD5(password||salt))。您可以在末尾使用-p 运行此命令,以将密钥、盐和IV 打印到控制台。 IV 确定性地从密码和盐中派生。推荐使用像 PBKDF2 这样的 KDF,但 OpenSSL 中的库函数由于某种原因不会将其暴露给命令行工具。
警告您可以运行此命令并指定 -nosalt 以跳过盐生成,但不建议这样做,因为它会使已经非常弱的 KDF 变得更弱。
密钥加密:
$ openssl enc -aes-256-cbc -in large_plain_file.dmg -out large_encrypted_file.enc K 0123456789ABCDEFFEDCBA98765432100123456789ABCDEFFEDCBA9876543210 -IV 0123456789ABCDEFFEDCBA9876543210
使用提供的实际密钥和 IV 运行。密钥为 32 字节(256 位),IV 为 16 字节(一个 AES 块的大小)。
要解密数据,请运行带有-d 标志的命令:
$openssl enc -aes-256-cbc -d -in large_encrypted_file.dmg -out large_decrypted_file.enc
这对您来说会更简单(无需证书/密钥对)并且更快(无需 RSA 加密)。
所有这一切都需要记住的是,如果您在命令调用中提供密码/密钥,密码/密钥将保留在终端历史记录中。在没有-k 或-K 的情况下运行将提示在安全提示中输入密码。或者使用-pass 从环境变量、文件或文件描述符中读取。
更新以明确解决原始问题:
- AES 密钥负责加密数据。 RSA 密钥用于加密 AES 密钥。
- 两者都会影响性能。 AES 密钥加密的数据要多得多,但比 RSA 加密要快得多。
- 是的,更改 RSA 密钥的大小会影响性能(密钥大小越大越慢),但对于大文件,这不太可能成为性能的限制因素。
- 是的,更改 AES 操作模式可能会对性能产生重大影响。 AES/CBC、AES/OFB 和 AES/CFB 的相似之处在于它们是串行操作(取决于一个块操作的结果进行下一个块操作),但 AES/CTR 作为流密码运行并且可以并行化为提供加密和解密。
- 见上面的答案。