C ++ windows client supports SSL mutual authentication

   C ++ windows client supports SSL mutual authentication, the server is a JAVA development, the certificate is used jks format. C ++ does not support certificate JKS format, so use openssl carried out under conversion.

  1, we need to first jks turn into a .p12 file

keytool -importkeystore -srckeystore demo.jks -destkeystore demo.p12 -srcstoretype jks -deststoretype pkcs12

 2, and then transferred into pem file .p12 file

openssl pkcs12 -nodes -in demo.p12 -out demo.pem

3, copy ----- BEGIN CERTIFICATE -----

----- END CERTIFICATE ----- to cacert.pem file

If there are cer certificate file format is available the following commands directly converted into cacert.pem

openssl x509 -inform der -in demo.cer -out cacert.pem

4, extract the private key

openssl pkcs12 -in demo.p12 -nocerts -nodes -out demo.key;
openssl rsa -in demo.key -out privkey.pem;

 

flow chart:

There are a few places to note:

1、SSL_load_error_strings();
 SSL_library_init();
 OpenSSL_add_all_algorithms();

Only needs to be performed once, even if behind the need to reconnect, do not need to call again. So we can put in the constructor.

 

2, when the general connection, the socket will be set to non-blocking, preventing the server is not online, need to be connected for a long time. But after setting a non-blocking, ssl_connect may connect fail, so the need for multiple connections.

So I own package next:

int CSslSocketClient::SSL_ShakeHands()
{
    int ssl_conn_ret = SSL_connect(m_ssl);
    if (ssl_conn_ret == 1)
    {
        return 0;
    }
    else if (ssl_conn_ret == -1)
    {
        int ssl_conn_err = SSL_get_error(m_ssl, ssl_conn_ret);
        if (SSL_ERROR_WANT_READ == ssl_conn_err ||
            SSL_ERROR_WANT_WRITE == ssl_conn_err) {
            //需要再次来进行握手
            return -2;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }
}

When the call out, if the return value is 0, indicating success, if it is -1, indicating a failure, if it is -2, the need ssl connection again.

 

3, because you want to support two-way authentication, so before SSL_new need to load the next certificate, and the next check.

    CString strPath;
    strPath.Format("%s\\pem\\%s", m_strWorkPath, CERT_NAME);
    if (SSL_CTX_use_certificate_file(m_ctx, strPath, SSL_FILETYPE_PEM) <= 0){
        MYTRACE("CSslSocketClient", "certificate file error!");
        DisconnectSocket();
        return -1;
    }

    strPath.Format("%s\\pem\\%s", m_strWorkPath, PRIV_NAME);
    if (SSL_CTX_use_PrivateKey_file(m_ctx, strPath, SSL_FILETYPE_PEM) <= 0){
        MYTRACE("CSslSocketClient", "use privatekey file Error: %s\n", ERR_reason_error_string(ERR_get_error()));
        DisconnectSocket();
        return -1;
    }
    if (!SSL_CTX_check_private_key(m_ctx)){
        MYTRACE("CSslSocketClient", "Check private key failed!\n");
        DisconnectSocket();
        return -1;
    }

4, the class destructor frees the memory ssl's memory, but there will still be around 2MB of memory leaks, not does not matter, anyway, this time the program has been pulled out.

     // 释放内存
    sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
    CRYPTO_cleanup_all_ex_data();

    ERR_remove_state(0);
    CONF_modules_unload(1);
    CONF_modules_free();
    ERR_free_strings();
    ERR_remove_thread_state(NULL);
    EVP_cleanup();

The above functions require the header file

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

 

Guess you like

Origin www.cnblogs.com/ahcc08/p/11302798.html