C ++用のOpenSSLAPIを使用しています。通信は、組み込みLinuxデバイス(SSLサーバー)とWindowsソフトウェア(SSLクライアント)の間で行われます。
目的のサーバーとクライアントが相互にのみ通信するようにしたい。以下とともに、サーバーのルートキーを生成しました。
ハンドシェイク中にサーバー証明書のみを承認する場合、SSL接続は正常に機能します。
ただし、クライアントの信頼性も確認したいので、次のように、クライアント用に別のルートキーを生成しました。
以下のコードを使用すると、次のエラーが原因でサーバーがクライアント接続を受け入れることができません。
724428760:エラー:140890B2:SSLルーチン:SSL3_GET_CLIENT_CERTIFICATE:証明書が返されませんでした:s3_srvr.c:3291:
SSL証明書に関連するサーバーコードは次のとおりです。
bool SSLServer::loadCertificates(const char * sCertFile,
const char * sKeyFile,
const char * sCAFile)
{
// set server certificate
if (SSL_CTX_use_certificate_file(_pCTX, sCertFile, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return false;
}
// set the private key
if (SSL_CTX_use_PrivateKey_file(_pCTX, sKeyFile, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
return false;
}
// verify private key
if (!SSL_CTX_check_private_key(_pCTX))
{
qWarning() << "Private key does not match the public certificate.";
return false;
}
SSL_CTX_set_verify(_pCTX, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
// load the trusted client CA certificate into context
if (SSL_CTX_load_verify_locations(_pCTX, sCAFile, NULL) != 1)
{
ERR_print_errors_fp(stderr);
return false;
}
// allow this CA to be sent to the client during handshake
STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(sCAFile);
if (NULL == list)
{
qWarning() << "Failed to load SSL client CA file.";
return false;
}
SSL_CTX_set_client_CA_list(_pCTX, list);
SSL_CTX_set_verify_depth(_pCTX, 1);
return true;
}
そして、これが私のクライアントコードです:
bool SSLClient::LoadCertificates(const char * sCAFile,
const char * sClientCertFile,
const char * sClientKeyFile)
{
ASSERT(NULL != sCAFile && NULL != sClientCertFile && NULL != sClientKeyFile);
// load RSA CA certificate into context to let client verify server's authenticity
// (will be used with server certificate and private key)
if (!SSL_CTX_load_verify_locations(_pCTX, sCAFile, NULL))
{
ERR_print_errors_fp(stderr);
return false;
}
// load client certificate into context to let server verify client's authenticity
// (will be used with server's RSA CA certificate)
if (SSL_CTX_use_certificate_file(_pCTX, sClientCertFile, SSL_FILETYPE_PEM) != 1)
{
ERR_print_errors_fp(stderr);
return false;
}
// load client certificate private key into context
if (SSL_CTX_use_PrivateKey_file(_pCTX, sClientKeyFile, SSL_FILETYPE_PEM) != 1)
{
ERR_print_errors_fp(stderr);
return false;
}
// verify that client cert and private key match
if (!SSL_CTX_check_private_key(_pCTX))
{
OutputDebugString("Private key does not match the certificate public key\n");
return false;
}
// require server certificate verification
SSL_CTX_set_verify(_pCTX, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
SSL_CTX_set_verify_depth(_pCTX, 1);
return true;
}
繰り返しますが、クライアント証明書の検証に関連するコードを削除すると、完全に正常に機能します。私は何かを逃しているのですか、それとも完全に間違っているのですか?
証明書と一緒にコードの作業コピー:http://files.webfile.ru/567c28b8973091cbdad036f3e43e989b
質問に答える「Enter」キーを押すだけで証明書を生成すれば、問題を正確に再現できます。あなたはそれを作る意図なしに「自己署名」証明書を手に入れるでしょう。OpenSSLとまったく同じ問題-深さ0のルックアップでのエラー18:自己署名証明書sslの問題をスヌーピングするときは、wiresharkではなくssldumpを使用する必要があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加