Ошибка SSL_CTX_use_PrivateKey_file()

Я пишу клиентское приложение в Windows, которое устанавливает SSL-соединение с сервером, и сервер запрашивает сертификат клиента для аутентификации. Сервер предоставляет мне файл .pfx, затем я использую инструмент командной строки openssl, чтобы получить сертификат и закрытый ключ следующим образом:

openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem
openssl pkcs12 -in filename.pfx -nocerts -out key.pem

после этого я пытаюсь загрузить сертификат и закрытый ключ с функциями из openssl, как показано ниже, но SSL_CTX_use_PrivateKey_file() всегда сбой, сообщение об ошибке "error:0906D06C:PEM routines:PEM_read_bio:no start line", я не могу понять, почему, может кто-нибудь дает мне некоторое просветление? Вот код.

#include "openssl/ssl.h"
#include "openssl/err.h"
#include <stdio.h>
#include <string>

int InitClientCtx()
{
    OpenSSL_add_ssl_algorithms();

    SSL_CTX* m_pClientCtx;
    m_pClientCtx = SSL_CTX_new(SSLv23_method());

    if(!m_pClientCtx)
    {
        return -1;
    }

    ::SSL_CTX_set_options(m_pClientCtx, SSL_OP_ALL);  //for well-known bugs

    int nRet = 0;

    std::string sCertFilePath = "C:\\cert.pem";

    nRet = SSL_CTX_use_certificate_chain_file(m_pClientCtx, sCertFilePath.c_str());

    std::string sKeyPassWord = "123456";

    SSL_CTX_set_default_passwd_cb_userdata(m_pClientCtx, (void*)(sKeyPassWord.c_str()));

    std::string sKeyFilePath = "C:\\key.pem";

    // this method returned 0, which means it failed.
    nRet = SSL_CTX_use_PrivateKey_file(m_pClientCtx, sKeyFilePath.c_str(), SSL_FILETYPE_PEM);

    SSL_load_error_strings();
    unsigned long n = ERR_get_error();
    char buf[1024];
    printf("%s\n", ERR_error_string(n, buf));

    nRet = SSL_CTX_check_private_key(m_pClientCtx);
    if (nRet <= 0)
    {
        return -1;
    }

    /*std::string sCACertFilePath;

    nRet = SSL_CTX_load_verify_locations(m_pClientCtx, sCACertFilePath.c_str(), NULL);*/

    return 0;
}

int main()
{
    InitClientCtx();
    return 0;
};

Ответ 1

Я сам решил эту проблему. Я сгенерировал key.pem, используя OpenSSL для Windows, когда CMD предложит мне ввести пропущенную фразу, Я просто набрал Enter, потому что мне не нужна фраза прохода, но key.pem был недействителен (ни BEGIN и END). Когда я сгенерирую закрытый ключ в Linux, подсказки терминала я должен ввести парольную фразу, и я это делаю. Затем я удаляю фразу для передачи ключа с помощью этой команды:

openssl rsa -in key.pem -out newkey.pem

После этого я открываю key.pem в текстовом редакторе, он начинается с -----BEGIN RSA PRIVATE KEY----- и заканчивается -----END RSA PRIVATE KEY-----. И SSL_CTX_use_PrivateKey_file() просто отлично работает!

Ответ 2

В моем случае ошибка состояла в том, что файл PEM не содержал ни ключа, ни сертификата.

Убедитесь, что файл содержит оба раздела:

-----BEGIN PRIVATE KEY----- jhajk838383jks.....
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE----- yoe55wjcxnshre.....
-----END CERTIFICATE KEY-----

Я привязал файлы .key и .crt, которые у меня уже были в моей конфигурации Apache, чтобы создать файл .pem.

Ошибка "без начальной строки", безусловно, вводит в заблуждение, так как вы можете иметь отличную строку "BEGIN" в вашем PEM файле и по-прежнему получать ошибку.

Ответ 3

Ошибка error:0906D06C:PEM routines:PEM_read_bio:no start line заключается в том, что и в файле cert.pem, и в key.pem не начинайте с -----BEGIN CERTIFICATE----- и -----BEGIN ENCRYPTED PRIVATE KEY-----.

Если вы откроете свой файл cert.pem и key.pem в текстовом редакторе и отбросьте все, что есть до маркеров BEGIN, вы должны быть хорошими.

Когда вы создаете сертификат и пару ключей, используя Запрос подписи сертификата, вы не получите эту дополнительную информацию.

Ответ 4

В каталоге openssl demo/openssl есть пример клиента.

Изменить:

meth = SSLv2_client_method();

в вашем случае:

meth = SSLv23_client_method();

Попробуйте этот пример и посмотрите, где он не работает.

Вы уверены, что пароль ключа 123456?

Ответ 5

У меня была такая же проблема в NGINX при установке сертификата SSL, и я решил ее следующим образом:

  • Перейдите в папку, где у вас есть сертификат и файлы pem.
  • Откройте файл ca-bundle.crt и скопируйте все, sudo nano your fileName выберите все и скопируйте. файл выглядит как

-----BEGIN CERTIFICATE----- MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT ..........

-----END CERTIFICATE-----

-----BEGIN CERTIFICATE----- MIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVT MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKEdv ..........

-----END CERTIFICATE-----

-----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE .......... -----END CERTIFICATE-----

  • Откройте файл pem, используя sudo nano your fileName.pem
  • Вы увидите код, подобный

-----BEGIN CERTIFICATE----- MIIGLzCCBRegAwIBAgIIWI4ndTQi3MwwDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIF oDA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkaWcy

-----END CERTIFICATE-----

  • После -----END CERTIFICATE----- вставьте весь код, скопированный из файла ca-bundle.crt, и сохраните его
  • Перезагрузите сервер Nginx с помощью следующей команды sudo service nginx restart

Вышеупомянутые шаги помогли мне в моей конфигурации Nginx и SSL