飞天诚信ePass3000系列数字证书文档签名+SSH硬件验证登录全流程
引言
首先说一下为什么要用物理安全密钥
数据的加解密和签名操作,均由密钥来进行,在非对称加密中也被称之为私钥和公钥。密钥和私钥要被严格保护以保障安全,常用的方式有存储在一个安全的服务器,或者硬盘甚至可移动设备中。为了防止密钥被窃取后轻而易举的被盗用,还可以对其密钥文件进行加密,但是知晓正确密码的人依然有能力获得私钥的具体内容并随意拷贝
而物理安全密钥却不同,虽然其表现出来只是换了个密钥的存储介质。可一旦证书在内部被生成或者从外部被导入,进入硬件的私钥将被永久存储在硬件中无法导出,即使是采用外部导入的方式,只要保证除硬件之外没有其它私钥副本,那么这个证书私钥就是安全的,这也是物理安全密钥根本区别于其它可移动可拷贝密钥存储方式的原因,最终数据的加密与签名操作均由硬件内部使用私钥处理得来,即使是拥有操作密码来进行签名,但被拔除物理硬件之后就无法再进行后续操作
因此可以预见,使用物理密钥的方式,既可以使用私钥验证的方式来避免使用密码带来的泄露风险,在公共主机中,也无需临时下载密钥文件,因此也能避免忘记删除密钥文件或被未知恶意软件窃取。物理安全密钥可以插在任何兼容设备上,并安全地签名数据,全程不会暴露密钥,使得在公共主机中安全连接服务器成为可能
本文内容篇幅较长且步骤繁多,完全理解需要花费一些时间
硬件&软件准备
介绍下本次硬件验证系列的核心组件,选用的是飞天诚信系列的身份认证系列,之前也有买过其他的硬件加密令牌,但大多是软件加密令牌,没有符合PKI规范以及提供PKCS#11接口的硬件,这次便之前选用飞天了。
顺带一提,现在银行的U盾以及附带的数字证书都基本是飞天的硬件,也有很多授权软件也是,包括现在有的这个DiskGenius授权
具体的软硬件准备有
- 飞天诚信身份认证系列ePass3003Auto
- Adobe Acrobat DC(用于PDF数字签名)
- Office Word(用于doc数字签名)
- OpenSSH Client(Windows附带)
ePass3003Auto似乎是目前在官网找到的最高配的ePass系列了(带GM的不谈),不过发布也有一段时日了,价格方面百元以内还能接受,而且3003系列将RSA密钥从1024bit升级到了2048bit,在如今的互联网环境下还是很重要的,而带Auto和不带的区别就是插入时会提供一个虚拟光驱方便你不需要下载就能直接安装中间件
图片我就不拍了,详细参数可以参考官网链接
生成与导入证书
关于证书的概念以及RSA公私钥非对称加密的相关内容,不会在此文章中赘述,理解下文的内容需要一些相关基础知识
证书是个容器,可以存储公钥和私钥,也可以只存储公钥用于公开,在这里是我们利用PKI认证体系完成以下的所有安全认证流程的媒介
生成证书
使用硬件签名,首先得要为设备存储证书。关于证书的申请与签署的方式五花八门。这个硬件也支持你使用提供的接口硬件生成并存储证书,但是我到现在还没有整明白,故采用从外部导入已经生成好的证书的方式
如果你有不错的经济基础,拥有权威CA机构签发的代码签名/文档签名证书(不能使用SSL证书),那么你可以直接跳过生成阶段导入该证书即可
简单的方式,就是用Adobe Acrobat DC自带的个人身份证书的方式进行生成,而且是自签名证书,缺点就是证书用途被限定于数字签名或加密解密,不过大多数场景下已经够用了
我是采用第三方工具来管理并生成证书,使用的是CertCloud的KeyManager,提供了简洁直观的界面,还可以完全自定义证书的预期用途和一些扩展字段,我的SSL证书私钥也是在这个软件上进行管理的,这两种证书生成方式都会详细说明
如果你之前接触过网站部署,可能会了解OpenSSL也可以生成自签名证书,具体相关的教程可自行查阅,一般会出现在部署诸如Nginx这类web服务时配置https证书时会提到,但是我并没有对使用该方式生成的证书进行测试
如果你对密钥的生成要求比较严格,想要确保密钥生成的过程中的安全,可以自行编程使用CAPI或者PKCS11规范接口与硬件交互,并利用硬件随机数生成器产生密钥,相关的说明文档,头文件与动态链接库,示例工程都会附带在硬件开发资料中
Adobe Acrobat DC生成自签名证书
首先打开Acrobat,找到编辑->首选项,并在左侧种类栏中找到签名,点击身份与可信任证书下的更多...

在弹出的数字身份证和可信任证书设置里,选择上侧证书详细信息旁一个带+号的按钮,开始创建新的证书

在添加数字身份证向导中,选择我要立即创新新数字身份证,下一步选择新建PKCS#12数字身份证文件,在下一步中填写相关信息。如果你打算正式使用此次创建的证书,那么里面的内容要认真填写,这些信息将会随着证书信息展示在所有被签名过的文件中,且无法更改

下一步就是为生成的证书文件指定导出位置了,并要求设置口令。强烈建议导出带密钥的证书时设置密码,在这里也是强制要求的,最后将会生成一个证书
但是到这里还没有结束,Acrobat会默认自动导入刚生成的证书,证书最终存储在本地不是我们所希望的,因此需要移除刚刚导入的证书。导出后会回到可信任证书设置框,可以看到刚刚自动导入的个人证书,存储机制为数字身份证文件,此时不能直接点击上方的删除身份证,因为这样也会同时删掉生成的证书文件

点击左侧数字身份证的小箭头展开树形结构,找到数字身份证文件,找到刚刚生成的数字身份证,选中并点击分离文件,自此Acrobat证书生成流程结束,可以在导出位置看到生成的*.pfx证书文件

使用KeyManager生成证书
KeyManager是一个证书管理工具,打开KeyManager后,我们需要先生成一个根证书,KeyManager默认并不支持自签名证书,我们需要先生成一个CA证书,再使用CA证书为这个证书签名
在证书管理中找到右上角创建测试证书按钮,往下拉找到证书签发者这一栏,点击创建根证书


通用名称起个名字,证书名就是证书信息看到的正式名称且不能修改,最好用xxxRootCA这类的字眼方便区分,CA证书是一类很特殊的证书不能随便混淆。KeyManager在输入框里提示输入的是某种域名不需要担心,这个工具默认是用于管理SSL证书的,所以生成的根证书默认也是用于SSL证书签署,实际上任意起名不会有任何影响
创建根证书后,就可以创建签名时使用的个人证书了。还是点击右上角的创建测试证书,填写这个证书的相关信息,带*的为必填项,在这里只会叙述一部分要点
同样的,通用名称即使提示输入域名,那也只是针对SSL证书而言的,还是按照自己的规则起一个证书名即可
证书类型除了服务器证书和客户端证书,这两种类型生成的证书无法在签名时被识别,其它类型均可,证书类型会影响到最终证书的用途,自定义则可以在底下的高级设置中自己配置密钥用途和扩展密钥用途,如果不懂这些属性的含义不建议乱选

有效期建议调长一点,默认是12个月,频繁更换很麻烦,接下来证书签发者选择刚刚生成的根证书,选择系统自动生成根证书会带来很多麻烦

证书生成后,在这个证书的操作栏选择更多,点击导出证书,服务器平台选择IIS(pfx/pkcs12),并建议设置加密私钥

导出了个人证书之后,还需要同时导出CA证书,选择CA证书选项卡,找到CA根证书并使用同样方式导出
以上两种生成方式选其一,均可得到.p12证书文件,不要去尝试双击打开导入,这样只会导入到本机,接下来就可以开始安装ePass管理工具开始导入证书了
导入证书
现在有了证书文件,先安装ePass3003Auto的管理工具,也会同时安装相关的PKCS11中间件,管理工具在后台的小图标是这样
双击小图标进入管理面板,截图的面板展示了我插入了一个硬件令牌

如果是刚拿到的新令牌,建议先使用文档中附带的管理工具(管理员版)初始化令牌,包括设置用户密码,SO PIN和令牌名等,这个操作只能在正式导入证书前进行,因为初始化过程会删除原有的全部数据
点击右侧登录,输入密码登陆到硬件令牌(初始密码说明书有),登录过后的令牌内是空空如也,点击下方的导入开始导入证书

不同的证书装在不同的容器之中,因此还需要新建一个容器,起一个与这个导入的证书相关的名字便于记忆,如果是使用KeyManager生成证书,根证书要单独一个容器存放(可见下图的样例)
在底下的用途中,如果是带有私钥的pfx证书这两个都没有区别,但如果是只有公钥的crt证书,选项就只有密钥交换。这个选项目前理解到的唯一用途是,一个容器可以装这两种用途的证书各一个,也就是说一个容器最多可以存储两个证书,而后续以相同的用途存储进来会导致旧的被替换,在发起数字签名和认证时,这两种用途的证书使用起来并没有什么限制,可能只是为了使用API的程序以此区分
导入证书后,私钥就被存储进硬件中,这是我目前已经完成的硬件令牌,每个容器我都单独存储了两个不同用途的证书,其中CA是根证书


确认证书导入无误后,就可以开始硬件令牌的使用了
数字签名
PDF数字签名
在打开Adobe Acrobat DC之前,请先插入物理令牌并确保识别正确
费了半天劲,如果上述的管理工具安装和证书导入没有问题,那么这一步就是最简单的了,打开Adobe Acrobat DC,并打开一个需要签名的PDF文件,在右侧打开签名面板

选择签名

接下来会要求你划定一个签名的位置,接着进入签名证书选择界面

如果证书导入无误,就能在这里看到你的个人证书,注意不要选择上面的根证书进行签名,选择继续后,选择签名样式并指定另存为的位置,便可以开始签名,按照提示输入硬件令牌的用户密码

然后签名就完成了,并且显示了已经被验证的签名

doc数字签名
其流程也是和PDF一样简单,先打开一个要签名的文档
如果你只是想用于测试,建议先把文档复制一份到一个临时位置再进行,因为在Office里签名会直接将修改应用到原文件中
签名也会导致文档被标记为最终状态,所以请确保签名前的文档已经是最终版本
在顶部栏进入文件,左侧选择信息选项卡,在保护文档按钮的下拉选项中找到添加数字签名

承诺类型我是没看出来选什么有区别,签署目的可以选填,还可以从详细信息进入填写更多信息

接下来点击底下的**更改...**选择签名所使用的证书,在弹出的选择对话框中点击更多选项可以列出所有可用证书,Office对签名限定的证书比较宽泛,可能会导致可供选择的证书更多,还是找到硬件令牌对应的证书,硬件证书会有不同的图标进行标识

如果在上述你是自行生成的证书,可能会在Office执行吊销检查时提示该信息

继续使用是没有问题的,使用权威CA机构颁发的证书不会有这个问题,同样的,在签名完成后的签名信息中,也会有类似的警告信息

接下来点击下一步,输入物理令牌的用户访问密码后,完成签名,文档也会标注为最终状态,如果此时发生文档的编辑,会导致签名失效需要重新签署
SSH硬件验证
硬件验证在实际使用时是很简单的,甚至可以不用安装上述的管理工具,以便可以在公共主机无需安装软件的情况下就可以使用硬件认证,而且也不会受限于证书生成时的预期用途,只是使用了证书承载的密码学数据内容,但是理解它的使用需要一些知识基础,以下只是概述
要理解以下内容,你必须先熟悉基本的ssh登录操作,并掌握公钥登录方式的配置
首先需要打开Windows的SSH Client支持,它不需要额外软件,在Windows 10 1809后自带,只要找到控制面板->程序->启用或关闭Windows功能,找到并勾选OpenSSH 客户端,点击确定并等待组件配置即可
如果你对Windows上使用OpenSSH客户端和服务端感兴趣,可以参考微软官方文档
接着要确认你的PKCS11中间件位置,这会在文档中说明,我的ePass3003在Windows平台为ShuttleCsp11_3003.dll
,如果你安装了管理工具,这个中间件会自动复制到C:\Windows\System32
目录里,如果你没有安装管理工具,可以在附带的文档资料中找到32位和64位两种版本的中间件可供直接使用
SSH硬件验证的部分,很大程度参考了另一个硬件令牌Yubikey的帮助文档,这里关于PKCS11进行SSH公钥认证,参考了这个文档
要进行SSH公钥认证,首先要先导出公钥存储到目标服务器,导出证书公钥有两种方法
使用SSH工具直接导出公钥
如果你之前生成过公私钥进行登录验证,你可能接触过ssh-keygen
工具,这个工具主要用于生成一个密钥对,同样的,这个工具也支持使用PKCS11中间件直接导出公钥
首先确保硬件令牌已经插入,然后在命令行输入以下命令,其中DLL文件路径是你的中间件位置
ssh-keygen -D C:\Windows\System32\ShuttleCsp11_3003.dll
不需要输入密码,稍等片刻就会导出一大串公钥,每行都是以ssh-rsa开头的OpenSSH风格的公钥,其顺序是对应管理工具中你导入证书的顺序,也是在证书树形图中由上至下展开的顺序,截图中管理工具只展示了前两个证书

找到你要用于认证的对应证书,并将这个公钥部署到目标服务器即可
从证书文件导出公钥(不推荐)
由于目前Windows版相关软件出现的问题,导致无法在纯Windows环境完成以下步骤,故不建议使用此方法
进入证书管理工具,选择要认证时使用的证书,点击右侧的导出,导出证书cer文件
接下来需要用到OpenSSL工具导出证书中的公钥,在Linux是默认自带的,若要在Windows下使用,需要手动下载安装,目前Windows版本的ssh-keygen和OpenSSL均会导致一些难以解决的问题,建议使用Linux进行以下操作,然后定位到存储证书的目录,输入
openssl x509 -inform der -in XX.cer -pubkey -noout > XX.pem
截止至发稿时,我使用的Windows版OpenSSL会导致输出的文件出现编码问题,在Linux下是标准UTF-8
接下来参考这篇文章,将PEM公钥转换为OpenSSH格式公钥
ssh-keygen -f xx.pem -i -m PKCS8
截至发稿时,Windows版ssh-keygen会出现上述命令没有任何输出的问题
关于ssh-keygen的参考,除了可以在Linux使用
man
指令查看帮助外,还可以在这里找到帮助文档
硬件认证登录
在成功导出了公钥(以ssh-rsa开头的公钥串)并部署到目标服务器后,就可以通过公钥登录的流程连接SSH了,只不过这次公钥对应的密钥并不在本机,而是安全地存储在硬件令牌中
现在开始连接ssh服务器,使用-I
参数指定提供密钥的中间件,并在后面指定登录使用的用户名和服务器地址
ssh -I C:\Windows\System32\ShuttleCsp11_3003.dll root@192.168.1.1
不要和
-i
参数混淆,那个是指定密钥文件的参数
如果你导出的公钥已经正确注册到目标服务器,那么首先会花费一些时间枚举硬件内所有的公钥,随后提示输入**PIN(用户密码)**以使用密钥

如果你的公钥没有正确注册,会提示相关错误
注意,如果是这样提示你输入用户密码用于登录,这意味着公钥注册没有成功,自动回退到了密码登录,继续输入账户密码登录会有安全风险

用户密码输入后,认证流程结束,进入到服务端命令行,自此硬件认证登录结束
写在后面
自此硬件令牌两个领域的应用(数字签名和登录认证)全流程就结束了,文章非常长,虽然就纯字数也才6k字,前期研究花费了几天的时间,文章的编辑更是花费了近一周的时间。从目前的使用体验来说,硬件认证便于迁移且安全,值得我采用这个方案使用很长一段时间
这款ePass3003Auto并不是很贵,100块不到能买到,如果你有经济基础想要有比较好的硬件认证体系,可以去考虑入手上文提到过的Yubikey,支持Linux平台的中间件,还有GPG密钥等功能的支持,但是价格较贵(大概300+),一些版本还带有NFC可以在手机上进行认证
另外还有一个必须要注意的点,上述自行生成的自签名证书仅供个人学习使用,不能将其用于政务或者其它需要签署具有法律效力的数字签名签署当中,这些签署必须是由你个人实名且由权威CA颁发的证书才能进行,一般只能见于商业个人数字签名证书,银行提供的带数字签名功能的U盾,或者由工商局等部门颁发的数字证书令牌,自行签署的证书不具备法律效力,且缺乏权威CA机构背书,所造成的后果由你自行负责
那么,就愉快地使用硬件安全认证体系吧