C++ windows客户端支持SSL双向认证,服务端是JAVA开发的,使用的证书是jks格式的。C++并不支持JKS格式的证书,所以要用openssl进行转换下。

1、 需要先把jks转成.p12文件

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

2、然后把.p12文件转成pem文件

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

3、拷贝-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----到cacert.pem文件里

如果有cer格式证书文件有可用下面的命令直接转成cacert.pem

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

4、提取私有key

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

流程图:

有几点注意的地方:

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

只需要执行一次即可,即使后面需要重新连接,也不需要再次调用。所以放在构造函数里可以里了。

2、一般连接的时候,都会把socket设置成非阻塞的,防止服务端不在线,需要连接很久。但是设置非阻塞之后,ssl_connect可能会连接失败,所以需要多次连接。

所以我自己封装了下:

int CSslSocketClient::SSL_ShakeHands()
{
int ssl_conn_ret = SSL_connect(m_ssl);
if (ssl_conn_ret == )
{
return ;
}
else if (ssl_conn_ret == -)
{
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 -;
}
else
{
return -;
}
}
else
{
return -;
}
}

外面调用的时候,如果返回值是0,说明成功,如果是-1,说明失败,如果是-2,说明需要再次ssl连接。

3、因为要支持双向认证,所以在SSL_new之前需要加载下证书,并check下。

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

4、类的析构函数里释放内存ssl的内存,但是仍然会有2MB左右的内存泄漏,不会也没有关系,反正这时候程序已经退出了。

     // 释放内存
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
CRYPTO_cleanup_all_ex_data(); ERR_remove_state();
CONF_modules_unload();
CONF_modules_free();
ERR_free_strings();
ERR_remove_thread_state(NULL);
EVP_cleanup();

上面的函数需要头文件

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

最新文章

  1. Makefile 编写 tips
  2. The RAII Programming Idiom
  3. java读取xml文件
  4. 成为 Linux 终端高手的七种武器 之七 条件执行&&
  5. Google搜索的几个使用技巧——让你的搜索结果更准确
  6. MessageFormat用法
  7. Objective-C( Foundation框架 一 数组(NSArray))
  8. sqlite使用小结
  9. 自己调用NTDLL函数
  10. 如何打包成jar包自己看呢?
  11. BCTF赛后
  12. Swift - 属性观察者(willSet与didSet)
  13. DiskFileUpload类别
  14. 使用JQUERY操作Radio
  15. [数据挖掘] - 聚类算法:K-means算法理解及SparkCore实现
  16. 简单背包问题(0032)-swust oj
  17. linux 虚拟机模拟配置网络路由环境-简版
  18. find the nth digit(二分查找)
  19. bzoj3124: [Sdoi2013]直径 树形dp two points
  20. LR参数化取值规则总结

热门文章

  1. 免费报名 | 汇聚HBase&amp;大数据最前沿 Apache HBaseConAsia2019盛会火热来袭
  2. linux 下 自己写的 html文件产生中文乱码问题 解决办法
  3. AtCoder Regular Contest 084 C - Snuke Festival【二分】
  4. 2018-2-13-win10-uwp-获取按钮鼠标左键按下
  5. select筛选用户数据
  6. React全家桶打造共享单车后台管理系统项目_第1篇_项目环境搭建_首页编写
  7. @总结 - 1@ 多项式乘法 —— FFT
  8. 使用jQuery的 autocomplete 实现输入框 自动提示补全
  9. selenium webdriver学习(五)------------iframe的处理(转)
  10. H3C 命令行帮助特性