SSL加密通信

HTTPS通信是在TCP通信层与HTTP应用层之间增加了SSL层,如果应用层不是HTTP协议也是可以使用SSL加密通信的,比如WebSocket协议WS的加上SSL层之后的WSS。

Socket连接建立后的SSL连接建立过程:

OpenSSL API

OpenSSL的API很多,但并不是都会被使用到,如果需要查看某个API的详细使用方法可以阅读API文档https://www.openssl.org/docs/man1.1.0/ssl/初始化OpenSSL

 OpenSSL在使用之前,必须进行相应的初始化工作。在建立SSL连接之前,要为Client和Server分别指定本次连接采用的协议及其版本,目前能够使用的协议版本包括SSLv2、SSLv3、SSLv2/v3和TLSv1.0。SSL连接若要正常建立,则要求Client和Server必须使用相互兼容的协议。   下面是Nebula框架SocketChannelSslImpl::SslInit()函数初始化OpenSSL的代码,根据OpenSSL的不同版本调用了不同的API进行初始化。

#if OPENSSL_VERSION_NUMBER >= 0x10100003L

    if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) == 0)
    {
        pLogger->WriteLog(neb::Logger::ERROR, __FILE__, __LINE__, __FUNCTION__, "OPENSSL_init_ssl() failed!");
        return(ERR_SSL_INIT);
    }

    /*
     * OPENSSL_init_ssl() may leave errors in the error queue
     * while returning success
     */

    ERR_clear_error();

#else

    OPENSSL_config(NULL);

    SSL_library_init();         // 初始化SSL算法库函数( 加载要用到的算法 ),调用SSL函数之前必须调用此函数
    SSL_load_error_strings();   // 错误信息的初始化

    OpenSSL_add_all_algorithms();

#endif

创建CTX

CTX是SSL会话环境,建立连接时使用不同的协议,其CTX也不一样。创建CTX的相关OpenSSL函数:

//客户端、服务端都需要调用
SSL_CTX_new();                       //申请SSL会话环境

//若有验证对方证书的需求,则需调用
SSL_CTX_set_verify();                //指定证书验证方式
SSL_CTX_load_verify_location();      //为SSL会话环境加载本应用所信任的CA证书列表

//若有加载证书的需求,则需调用
int SSL_CTX_use_certificate_file();      //为SSL会话加载本应用的证书
int SSL_CTX_use_certificate_chain_file();//为SSL会话加载本应用的证书所属的证书链
int SSL_CTX_use_PrivateKey_file();       //为SSL会话加载本应用的私钥
int SSL_CTX_check_private_key();         //验证所加载的私钥和证书是否相匹配 

 创建SSL套接字

在创建SSL套接字之前要先创建Socket套接字,建立TCP连接。创建SSL套接字相关函数:

SSL *SSl_new(SSL_CTX *ctx);          //创建一个SSL套接字
int SSL_set_fd(SSL *ssl, int fd);     //以读写模式绑定流套接字
int SSL_set_rfd(SSL *ssl, int fd);    //以只读模式绑定流套接字
int SSL_set_wfd(SSL *ssl, int fd);    //以只写模式绑定流套接字

完成SSL握手

 在这一步,我们需要在普通TCP连接的基础上,建立SSL连接。与普通流套接字建立连接的过程类似:Client使用函数SSL_connect()【类似于流套接字中用的connect()】发起握手,而Server使用函数SSL_ accept()【类似于流套接字中用的accept()】对握手进行响应,从而完成握手过程。两函数原型如下:

int SSL_connect(SSL *ssl);
int SSL_accept(SSL *ssl);

 握手过程完成之后,Client通常会要求Server发送证书信息,以便对Server进行鉴别。其实现会用到以下两个函数:

X509 *SSL_get_peer_certificate(SSL *ssl);  //从SSL套接字中获取对方的证书信息
X509_NAME *X509_get_subject_name(X509 *a); //得到证书所用者的名字

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐