boost 实现双向认证解决办法
boost::asio::ssl::context
- 要与OpenSSL进行相互认证,必须在客户端使用
SSL_VERIFY_PEER
在服务器端使用SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
。如果仅在服务器端使用SSL_VERIFY_PEER
,则它将仅将证书请求发送给客户端,但是如果客户端未发回证书,则将静默接受。 - ctx.set_verify_mode(ssl::verify_peer); // client side
- ctx.set_verify_mode(ssl::verify_peer|ssl::verify_fail_if_no_peer_cert); // server side
– 服务端证书的Common Name
得与ip|域名
相同
– 服务端只检测客户端证书的根ca
set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert) //配置启用双向认证
// 也能用ssl_socket调用 (typedef ssl::stream<tcp::socket> ssl_socket)
ssl_socket.set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert) //配置启用双向认证
ssl_socket.set_verify_callback(boost::asio::ssl::rfc2818_verification(url.server)); //验证证书与host是否匹配
load_verify_file(file) //加载信任的根证书 文件
add_certificate_authority(buffer) //加载信任的根证书 内容
use_certificate_chain_file //加载自己的证书 文件
use_private_key_file //加载自己的私钥 文件
openssl
openssl使用ECDSA对网络浏览器进行身份验证
openssl s_client -connect wikipedia.org:443
openssl实现双向认证解决办法
双向认证的关键点在以下几个函数(服务端和客户端都一样)
SSL_CTX_set_verify ----配置启用双向认证
SSL_CTX_load_verify_locations ----加载信任的根证书
SSL_CTX_use_certificate_file ----加载自己的证书
SSL_CTX_use_PrivateKey_file ----加载自己的私钥
SSL_get_verify_result ----真正进行验证,一定要调用这个函数不然前面四个光配置而已并不会进行双向验证
以下是SSL握手的具体流程:
(1)客户将自己的SSL版本号、加密参数、与SSL会话有关的数据及其他一些必要信息发送到服务器。
(2)服务器将自己的SSL版本号、加密参数、与SSL会话有关的数据及其他一些必要信息发送给客户,同时发给客户的还有服务器的证书。如果服务器需要验证客户身份,服务器还会发出要求客户提供安全证书的请求。
(3)客户端验证服务器证书,如果验证失败,就提示不能建立SSL连接。如果成功,那么继续下一步骤。
(4)客户端为本次SSL会话生成预备主密码(pre-master secret),并将其用服务器公钥加密后发送给服务器。
(5)如果服务器要求验证客户身份,客户端还要对另外一些数据签名后,将其与客户端证书一起发送给服务器。
(6)如果服务器要求验证客户身份,则检查签署客户证书的CA(Certificate Authority,证书机构)是否可信。如果不在信任列表中,结束本次会话。如果检查通过,服务器用自己的私钥解密收到的预备主密码(pre-master secret),并用它通过某些算法生成本次会话的主密码(master secret)。
(7)客户端与服务器端均使用此主密码(master secret)生成此次会话的会话密钥(对称密钥)。在双方SSL握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量要低一个数量级以上,能够显著提高双方会话时的运算速度。
(8)客户端通知服务器此后发送的消息都使用这个会话密钥进行加密,并通知服务器客户端已经完成本次SSL握手。
(9)服务器通知客户端此后发送的消息都使用这个会话密钥进行加密,并通知客户端服务器已经完成本次SSL握手。
(10)本次握手过程结束,SSL会话已经建立。在接下来的会话过程中,双方使用同一个会话密钥分别对发送和接收的信息进行加密和解密。