我建议使用带有可靠加密模块的现有 S/MIME(或 CMS)实现来加密您的内容。
S/MIME 封装数据为“静态”加密数据的存储提供了一种很好的格式:信封记录了有关所使用的算法和密钥的信息,以便授权接收者稍后在需要时可以使用这些信息。
此外,即使它不支持“最佳”算法(如 ECDH 密钥协议),与一般程序员编写的库相比,好的库也不太可能存在漏洞。由于实施错误比密码分析更有可能破坏安全性,因此将这些错误最小化是有意义的。
在合法协议中,公钥由少数受信任的发行者之一签名,其公钥通过某种安全方式“带外”分发。如果您已经有一种安全的方法来获取消息发送者的公钥,为什么还要发送另一个呢?如果你不这样做,你就完蛋了。
TLS 和 S/MIME 依赖于每个客户端都有一组众所周知的 CA 证书。这些用于签署服务器的公钥,以便客户端可以检测到替换密钥的尝试。协议不能自举;必须有一种安全的方式在带外分发“信任锚”。
另请注意,与对称密码相比,RSA 速度非常慢。真实协议为 AES 等对称算法生成“内容加密密钥”,然后使用 RSA 公钥作为“密钥加密密钥”为消息接收者加密内容加密密钥。
因此,主要问题是将您的公钥安全地提供给客户端。如果你能做到这一点,那么选项#1 或#2 都是好的——假设你只使用那个公钥,而不是尝试“带内”发送另一个公钥。实际上,在CMS中,选项#1 称为“密钥传输”,选项#2 称为“密钥协议”。
在实践中,“服务器”可以使用由众所周知的 CA 颁发的证书,或者客户端可以将证书的哈希值与您通过电话告诉他的证书进行比较,或者刻在悬崖上,管他呢。关键是,您所有的安全性都取决于证书的完整性。你必须保护它不被篡改。
虽然 Crypto++ 是“行业标准”,但其安全性取决于您如何使用它。 就像 Jerry 对 Kramer 说的那样, “门必须……关上! ”在设计不佳的协议中使用 Crypto++ 中的加密原语会让你一事无成。这就是为什么我要强调使用 CMS(一种更高级别的协议)和一个好的密码模块(密码原语)。