Reading Public/Private Key from Memory with OpenSSL

后端 未结 3 654
予麋鹿
予麋鹿 2020-12-06 07:02

I am using Public/Private Keys in my project to encrypt/decrypt some data.

I am hosting a public key (\"public.pem\") on a server.

\"public.pem\" looks like

相关标签:
3条回答
  • 2020-12-06 07:42

    SquareRootOfTwentyThree's method not work for me. Here is my solution.

    BIO* bio = BIO_new(BIO_s_mem());
    int len = BIO_write(bio, pem_key_buffer, pem_key_buffer_len);
    EVP_PKEY* evp_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
    RSA* rsa = EVP_PKEY_get1_RSA(evp_key);
    
    0 讨论(0)
  • 2020-12-06 07:46

    Here's complete example, showing embedded key, and how to use C++11 unique pointers to manage OpenSSL resources.

    Updated: following on from comments by spectras. No longer using specialisation of 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;
    }
    
    0 讨论(0)
  • 2020-12-06 07:54

    You are on the right track. You must wrap the PEM key already in memory by means of a BIO buffer via BIO_new_mem_buf(). In other words, something like:

    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);
    

    The same approach is valid for an RSA private key (via PEM_read_bio_RSAPrivateKey), but in that case you most certainly need to cater for the pass phrase. Check the man page for details.

    0 讨论(0)
提交回复
热议问题