为 openssl EVP_PKEY 私钥清理内存的 C 代码

Posted

技术标签:

【中文标题】为 openssl EVP_PKEY 私钥清理内存的 C 代码【英文标题】:C code to clean up memory for openssl EVP_PKEY private keys 【发布时间】:2017-03-18 00:04:35 【问题描述】:

我开始学习 C/C++ 中的 OpenSSL 编程。我遇到的一个问题是,我怎样才能安全地清除私钥的内存?

例如,我可能有代码:

EVP_PKEY *private_key = PEM_read_bio_PrivateKey( bio, ,,,)
RSA *r = EVP_PKEY_get1_RSA( private_key);

我想在使用 EVP_PKEY_free() 释放它之前彻底清除内存中的 private_key。

非常感谢您的帮助和/或您的建议。 谢谢。

【问题讨论】:

memset(...) 会为你工作吗? 安全清除记忆是一个复杂的课题。这取决于实现如何实现这一点。请注意,不仅是擦除密钥。如果您想阻止其他进程,例如,读取它们并存储已经是一个问题。读取内存。 【参考方案1】:

EVP_PKEY *private_key = PEM_read_bio_PrivateKey( bio, ,,,)

我想在使用EVP_PKEY_free 释放它之前从内存中彻底清除 private_key。

OpenSSL 的EVP_PKEY_free 会为您擦除私钥。你不必做任何特别的事情。

RSA *r = EVP_PKEY_get1_RSA( private_key);

get1 表示引用计数已增加,您有效地获得了自己的对象副本。 get0 表示您有一个指向现有对象的指针,您应该在其上调用free。由于get1,您必须调用RSA_free 以确保它被删除。与EVP_PKEY_free 一样,RSA_free 将擦除密钥。

请不要拨打memset。这些是不透明的结构,您必须遵循许多指针才能正确清除子对象。 OpenSSL 1.1.0 中隐藏了更多的字段,因此(如果您愿意的话)将更加难以遵循指针。另见Error: “invalid use of incomplete type ‘RSA aka struct rsa_st” in OpenSSL 1.1.0、Visual Studio and error C2027: use of undefined type 'rsa_st' in OpenSSL 1.1.0、EVP_get_cipherbyname and “undefined struct/union evp_cipher_st” in OpenSSL 1.1.0等


以下是您可能感兴趣的一些额外阅读:

Why does OPENSSL_cleanse look so complex and thread-unsafe? Removing OPENSSL_cleanse from OpenSSL-1.0.1r

当调用EVP_PKEY_freeRSA_free 之类的函数时,它们最终会在内存返回给操作系统之前以调用OPENSSL_cleanse 结束。对于 RSA 私钥,它至少调用 8 次以擦除与 nedpqdpdq 关联的字节数组,和invq

【讨论】:

jww,非常感谢。我检查了我正在使用的 openssl 1.0.1u 的源代码。我没有看到从 EVP_PKEY_free() 调用的任何 OPENSSL_cleanse() 调用。但我确实看到很多从 RSA_free() 调用的 OPENSSL_cleanse()。由于 rsa 密钥只是来自 EVP_PKEY 结构内存区域的引用,我可以安全地假设当我执行 RSA_free() 时,它会擦除​​ rsa 密钥,因此它还清理了 EVP_PKEY 结构的内存? EVP_PKEY_free() 最终调用EVP_PKEY_free_it(),它使用EVP_PKEY 结构的ameth 指针调用负责清理特定密钥类型的私钥数据的函数... 抽象,抽象无处不在!

以上是关于为 openssl EVP_PKEY 私钥清理内存的 C 代码的主要内容,如果未能解决你的问题,请参考以下文章

将 NSData 转换为字符串?

php的openssl_sign($data,$sign,$private_key)这个函数的源码是啥?

openssl从内存中读取私钥进行签名

使用 OpenSSL 和公钥 ssh-keygen 为 SSH 生成私钥

Openssl 将仅包含 RSA 私钥的 .PEM 转换为 .PKCS12

使用 RSA 公钥在 Openssl 中生成私钥?