使用OpenSSL从内存中读取公钥/私钥

use*_*031 6 c ssl openssl

我在我的项目中使用公钥/私钥来加密/解密一些数据.

我在服务器上托管公钥("public.pem").

"public.pem"看起来像这样:

-----BEGIN PUBLIC KEY-----
.....
.....
-----END PUBLIC KEY-----
Run Code Online (Sandbox Code Playgroud)

我编写了一个客户端,下载此公钥并将其保存到磁盘,然后使用文件描述符将OpenSSL的PEM_read_RSA_PUBKEY()调用到该文件.此操作很有效,结果是一个准备加密的RSA对象.

我想避免每次都将公钥写入磁盘(因为我已经在内存中有缓冲区).

如何在不将缓冲区保存到磁盘的情况下执行相同的操作?我注意到一个名为PEM_read_bio_RSAPublicKey()的函数,但我不确定它是否使用了BIO结构.我在正确的道路上吗?

所以真正的问题是:如何直接从内存而不是文件描述符中读取RSA对象的公钥/私钥.

Squ*_*ree 17

你走在正确的轨道上.您必须通过BIO缓冲区将PEM密钥包装在内存中BIO_new_mem_buf().换句话说,像:

BIO *bufio;
RSA *rsa

bufio = BIO_new_mem_buf((void*)pem_key_buffer, pem_key_buffer_len);
PEM_read_bio_RSAPublicKey(bufio, &rsa, 0, NULL);
Run Code Online (Sandbox Code Playgroud)

相同的方法对RSA私钥(via PEM_read_bio_RSAPrivateKey)有效,但在这种情况下,您肯定需要满足密码短语.有关详细信息,请查看手册页.


Dar*_*ith 5

下面是完整的示例,显示了嵌入密钥以及如何使用 C++11 唯一指针来管理 OpenSSL 资源。

更新:根据spectrum的评论进行更新。不再使用专业化default_delete<T>.

/* compile with:

    c++ -Wall -pedantic  -std=c++17 main.cc  -lssl -lcrypto -o main
*/

#include <memory>
#include <iostream>

#include <openssl/err.h>
#include <openssl/pem.h>

#include <assert.h>
#include <string.h>

/* Custom deletors for use with unique_ptr */

struct EVP_PKEY_deleter {
  void operator()(EVP_PKEY* p) const {
      if (p)
        EVP_PKEY_free(p);
  }
};

struct BIO_deleter {
  void operator()(BIO* p) const {
      if (p)
        BIO_free(p);
  }
};

/* Smart pointers wrapping OpenSSL resources */

using evp_key_ptr = std::unique_ptr<EVP_PKEY, EVP_PKEY_deleter>;
using bio_ptr = std::unique_ptr<BIO, BIO_deleter>;

/* Create key based on memory contents */

evp_key_ptr load_public_key(const char* buf, size_t len)
{
  bio_ptr bp (BIO_new_mem_buf((void*) buf, len));
  if (!bp)
    throw std::runtime_error("BIO_new_mem_buf failed");

  EVP_PKEY * kp = nullptr;

  kp = PEM_read_bio_PUBKEY(bp.get(), &kp, nullptr, nullptr);
  ERR_print_errors_fp(stderr);
  return evp_key_ptr{kp};
}


int main()
{
  const char * RSA_PUBLIC_KEY=R"(
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA80ZqDPPW5eOH6TWdLsEJ
8qf6hoMJfFZ3BL9Fz+YNGeBpF3zxKmm8UuRrBHHVZZB2Gs1MTo06IU3fqDfFsOyh
J6pHeJF3wyUlYZuYbGAyMlZZ/+M5TOvo92f7lt/A40QThCVf1vS5o+V8sFkgnz3N
C7+VvC4dYrv+fwnmnWGxPy1qfp3orB+81S4OPRiaoy+cQBZs10KCQaNBI/Upzl2R
3dMkWKM+6yQViKTHavT4DRRZ1MKp9995qOR3XfhhJdWuDl4moXcU3RcX4kluvS5q
b8oTnVyd2QB1GkUw6OKLWB/5jN1V1WzeYK447x2h4aPmJfsn5gCFJs6deq2RFQBR
SQIDAQAB
-----END PUBLIC KEY-----
)";
  ERR_load_crypto_strings();
  ERR_free_strings();

  auto pubkey = load_public_key(RSA_PUBLIC_KEY, strlen(RSA_PUBLIC_KEY));
  if (pubkey)
    std::cout << "load_public_key success" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)