USBKey使用openssl链接
Openssl对USBKey的研究
1. USBKey
USBKey是一种USB接口的硬件设备。它内置单片机或智能卡芯片,有一定的存储空间,可以存储用户的私钥以及数字证书,利用USB Key内置的公钥算法实现对用户身份的认证。由于用户私钥保存在密码锁中,理论上使用任何方式都无法读取,因此保证了用户认证的安全性。
2. Openssl
OpenSSL 是一个强大的安全套接字层密码库,囊括主要的密码算法、常用的密钥和证书封装管理功能及SSL协议,并提供丰富的应用程序供测试或其它目的使用。
SSL是Secure Sockets Layer(安全套接层协议)的缩写,可以在Internet上提供秘密性传输。Netscape公司在推出第一个Web浏览器的同时,提出了SSL协议标准。其目标是保证两个应用间通信的保密性和可靠性,可在服务器端和用户端同时实现支持。已经成为Internet上保密通讯的工业标准。
SSL能使用户/服务器应用之间的通信不被攻击者窃听,并且始终对服务器进行认证,还可选择对用户进行认证。SSL协议要求建立在可靠的传输层协议(TCP)之上。SSL协议的优势在于它是与应用层协议独立无关的,高层的应用层协议(例如:HTTP,FTP,TELNET等)能透明地建立于SSL协议之上。SSL协议在应用层协议通信之前就已经完成加密算法、通信密钥的协商及服务器认证工作。在此之后应用层协议所传送的数据都会被加密,从而保证通信的私密性。
Openssl的知识不是一下两下能说完的,后面再详细解释openssl的具体功能,这里直接切入正题,看看openssl是怎么驱动USBKey的。
3. Openssl引擎
Engine机制目的是为了使OpenSSL能够透明地使用第三方提供的软件加密库或者硬件加密设备进行加密。OpenSSL的Engine机制成功地达到了这个目的,这使得OpenSSL已经不仅仅使一个加密库,而是提供了一个通用地加密接口,能够与绝大部分加密库或者加密设备协调工作。当然,要使特定加密库或加密设备更OpenSSL协调工作,需要写少量的接口代码,但是这样的工作量并不大,虽然还是需要一点密码学的知识。Engine机制的功能跟Windows提供的CSP功能目标是基本相同的。
4. Engine-pkcs11
engine_pkcs11是opensc开源工程开发的PKCS#11的一个引擎,可以直接支持openssl。利用它可以实现openssl和USBKey的接口。
Openssl加载engine-pkcs11引擎库的时候要调用engine_pkcs11源码中的bind_fn函数,来设置一些参数,具体代码如下所示:
if (!ENGINE_set_id(e, PKCS11_ENGINE_ID) ||
!ENGINE_set_destroy_function(e,pkcs11_engine_destroy) ||
!ENGINE_set_init_function(e, pkcs11_init)||
!ENGINE_set_finish_function(e,pkcs11_finish) ||
!ENGINE_set_ctrl_function(e,pkcs11_engine_ctrl) ||
!ENGINE_set_cmd_defns(e, pkcs11_cmd_defns)||
!ENGINE_set_name(e, PKCS11_ENGINE_NAME) ||
#ifndef OPENSSL_NO_RSA
!ENGINE_set_RSA(e, PKCS11_get_rsa_method())||
#endif
#ifndef OPENSSL_NO_DSA
!ENGINE_set_DSA(e,DSA_get_default_method()) ||
#endif
#ifndef OPENSSL_NO_DH
!ENGINE_set_DH(e, DH_get_default_method())||
#endif
!ENGINE_set_RAND(e, RAND_SSLeay()) ||
#if 0
!ENGINE_set_BN_mod_exp(e, BN_mod_exp) ||
#endif
!ENGINE_set_load_pubkey_function(e,pkcs11_load_public_key) ||
!ENGINE_set_load_privkey_function(e,pkcs11_load_private_key) ) {
return 0;
} else {
return 1;
}
主要包括引擎初始化,主要是初始化一些回调函数,包括导入私钥、导入公钥、导入证书。由于这里没有导入证书的接口,所以需要增加一个导入证书的接口函数,增加如下代码:
!ENGINE_set_load_ssl_client_cert_function(e,load_ssl_client_cert)
其中load_ssl_client_cert是导入证书,这个函数源码中没有实现需要自己实现。后面着重实现这部分代码。
5. 实现
这是openssl对USBKey实现的步骤,他采用openssl引擎的机制来调用USBKey的接口实现证书的认证等一系列过程。本次采用的USBKey为海泰生产的USBKey。在这里介绍一下怎么样使用USBKey通过openssl和服务器进行ssl链接。
首先启动openssl。启动的时候用root用户来启动。否则在操作USBKey设备的时候会失败。
第二、加载引擎,这里的引擎使用engine-pkcs11提供的引擎方法。这里的引擎有个接口方法没有实现,需要自己来实现这个接口。后面再解释。加载引擎的方法为:
engine -t dynamic -pre SO_PATH:/usr/local/lib/engines/engine_pkcs11.so-pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -preMODULE_PATH:/home/wuyan/rockontrol/haikey.RAR/haikey-0.2.4/lib/htpkcs11.so
其中SO_PATH为pkcs11的引擎,ID为引擎的id,就是后面调用引擎的名字。MODULE_PATH为USBKey的驱动,也就是USBKey的接口函数。结果如下:
(dynamic) Dynamic engine loading support
[Success]:SO_PATH:/usr/local/lib/engines/engine_pkcs11.so
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
[Success]:MODULE_PATH:/home/wuyan/rockontrol/haikey.RAR/haikey-0.2.4/lib/htpkcs11.so
Loaded: (pkcs11) pkcs11 engine
[ available ]
如果是available说明你的引擎调用成功了。
第三就是进行ssl链接,openssl的s_client工具实现了简单的ssl连接。可以通过它来做ssl链接的测试。在和服务器进行ssl链接的时候,需要读取USBKey中的公钥、私钥和证书。为了使用第二步加载的引擎,需要使用engine参数来指名引擎的id,引擎的id在第二步已经设置过为pkcs11,engine-pkcs11引擎中为了找到对应的证书需要提供一个USBKey对应的id号。通过key参数来指定。有了这两个参数就可以通过openssl引擎正确读取USBkey的公钥和私钥了,但是还不能正确的获取证书,获取证书在openssl中必须通过ssl3协议进行ssl链接。所以需要指定ssl3参数。然后指定client_engine pkcs11这个参数就是指定导入客户端证书的回调函数。也就是在上面实现的load_ssl_client_cert,在进行ssl连接的时候需要导入证书,否则失败。然后用s_client测试就可以。命令如下:
s_client -engine pkcs11 -key id_ebda8c5d40140168c4e0078f41b995ca3dad981f -keyform engine -ssl_client_engine pkcs11-ssl3 -connect ***.***.***.***:443
6. 获取证书的实现
在第四节的时候我们在引擎中增加了一个获取证书的接口,它在engine_pkcs11中没有实现,这里我们就介绍一下他的实现。首先我们先看openssl是怎么获取证书的,因为我们是用ssl3协议进行连接,在s3_clnt.c文件中int ssl3_send_client_certificate(SSL *s)函数中有ssl_do_client_cert_cb(s,&x509, &pkey)函数,次函数就是要获取客户端证书。他会调用ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
SSL_get_client_CA_list(s),
px509,ppkey, NULL, NULL, NULL);
进而调用
e->load_ssl_client_cert(e, s, ca_dn,pcert, ppkey, pother,
ui_method,callback_data);
这就是我们上面所设置的回调函数。从上面可以看出我们只需要&x509, &pkey这两个东西,所以在回调函数中就是要获取这两个东西。好在engine_pkcs11已经提供了这两个函数的接口。贴代码吧:
int load_ssl_client_cert(ENGINE *e, SSL *ssl,
STACK_OF(X509_NAME)*ca_dn, X509 **pcert, EVP_PKEY **pkey,
STACK_OF(X509)**pother, UI_METHOD *ui_method, void *callback_data)
{
*pcert= pkcs11_load_cert(e, "ebda8c5d40140168c4e0078f41b995ca3dad981f");
if(*pcert == NULL)
return0;
*pkey= pkcs11_load_key(e, "ebda8c5d40140168c4e0078f41b995ca3dad981f",NULL, NULL, 0);
if(*pkey == NULL)
return0;
return1;
}
其中ebda8c5d40140168c4e0078f41b995ca3dad981f为USBKey的id号,当然也可以自动去USBKey中读取。其中pkcs11_load_cert和pkcs11_load_key都可以在engine_pkcs11引擎中找到原形。然后重新编译使用吧。
先学到这里,后面继续优化。下一章介绍ssl链接的流程
USBKey使用openssl链接相关推荐
- fatal error: openssl/evp.h: 没有那个文件或目录
在陆佳华<嵌入式系统软硬件协同设计实战指南 第2版>一书的第13章节 编译U-boot时会遇到2个错误.原因很简单,就从一开始的错误提示着手: fatal error: openssl/e ...
- Centos7 升级稳定版 openssl
openssl 源码包:https://www.openssl.org/source/ yum install gcc-c++ pcre pcre-devel zlib zlib-devel open ...
- Ubuntu下mingw和aarch64交叉编译x264/x265/openssl/freetype2的ffmpeg
1.ffmpeg下载 前往ffmpeg官网下载地址下载需要的最新ffmpeg发布版本 2.ffmpeg编译选项说明 在ffmpeg官网中有对ffmpeg编译选项的部分说明内容如下: --enable- ...
- 解决引用openssl静态库libcrypto.a和libssl.a出现undefined reference to错误的问题
解决引用openssl静态库libcrypto.a和libssl.a出现undefined reference to错误的问题 最近在做使用openssl链接http和https的项目,编译时出现以下 ...
- MinGW64编译OpenSSL
引言 用Qt写爬虫的时候,缺少openssl的动态库,试了几个已有的版本都不对,于是从官网下载了对应版本的源码自己编译. 准备 环境 我的Qt原工程环境是, MinGW7.3.0-x64(gcc ...
- 源码编译更新nginx到最新版本,并开始nginx支持http2协议模块.
最近因为迁移公司vm上的代码,遇到一些问题.有一台vm配置了https协议,原以为迁移安全证书以后,配置nginx就可以了,但是修改nginx配置文件以后,执行 nginx -t 命令后,报如下错误: ...
- TLS协议分析 (九) 现代加密通信协议设计
六. TLS协议给我们的启发 - 现代加密通信协议设计 在看了这么多的分析和案例之后,我们已经可以归纳出加密通信协议设计的普遍问题,和常见设计决策, 设计决策点: 四类基础算法 加密/MAC/签名/密 ...
- linux练习平台WarGame之bandit通关日志
前言~ Bandit是一个学习linux命令的闯关游戏平台,比较类似于ctf,通过闯关的模式,不断的学习新的命令,对于程序员亦或者安全爱好者来说都是一个不错的学习平台 传送门 目录导航 Level 0 ...
- 百度AI图像识别 C++ SDK环境配置
经过将近一周的摸爬滚打,终于把环境给搭起来了,虽然最后还有一点点小问题没解决........ 好吧,我刚看到这个的时候是懵的,根本不知道libcurl,openssl,jsoncpps是啥,菜鸟实锤. ...
- BlackArch-Tools
BlackArch-Tools 简介安装在ArchLinux之上添加存储库从blackarch存储库安装工具替代安装方法BlackArch Linux Complete Tools List 简介 B ...
最新文章
- php连接mysql页面空白_求大神: php注册页面跳转出现空白页
- Android数据存储之SQLite的操作
- Spark _26_Spark On Hive的配置
- L型代码结构案例:Link访问权限(上)
- Python函数式编程-map()、zip()、filter()、reduce()、lambda()
- Android带三角形的弹窗,Android实现三角形气泡效果方式汇总
- CF 961E Tufurama
- 使用Tika进行文本抽取
- ORB-SLAM2 窗口显示Viewer线程
- 设计模式 ( 一 ) 单例模式
- 圣思园java笔记_最详细JAVA高并发多线程VIP课程--圣思园--笔记
- 原生开发什么意思_原生app开发是什么意思?
- python里sample_python中的sample什么意思
- html制作一个视频播放器,H5 打造属于自己的视频播放器(HTML 篇)
- mysql neq什么意思_【知识科普】标准中的Eqv、Idt和Neq分别代表什么?
- Qt 解析 DXF 文件
- 有趣的游戏-猜黑白纸
- python有道字典_Linux下自制有道词典 - python 解密有道词典JS加密
- 世界顶级黑客,能入侵一台没有联网的电脑吗?
- 分享一款多功能免费SEO工具箱-从0开始打造高流量网站