陈琢,陈强
(成都卫士通信息产业股份有限公司,成都610041)
随着信息安全需求的发展,密码技术已得到广泛的使用,成为信息时代中不可获缺的组成部分。同时,为了提高密码运算的性能,提高密钥等关键信息的安全性,例如USBKey、加密TF 卡、贴芯卡等专门的密码设备应运而生,越来越多的系统使用这些密码设备来分担密码运算操作。为了给应用开发人员便利地调用这些密码设备,多个国际、国内的加密API 标准随即出现。这类标准为应用隐藏了密码设备的实现细节,为应用开发者提供统一的方式来使用不同的密码设备,大大增强了应用的可扩展性[1]。其中,PKCS#11[2]和SKF[3]是使用较广泛的两种。
国家密码管理局于2010 年首次发布《智能IC 卡及智能密码钥匙密码应用接口规范》,即SKF 接口标准。之后于2012 年11 月更新为GM/T0016-2012《智能密码钥匙密码应用接口规范》发布。目前很多国内密码设备厂商都为其产品提供了SKF 接口的开发包。随着国密技术的发展,SKF 接口在加密模块和软件上的使用已越发广泛。
在SKF 接口规范中,一个设备中存在一个设备认证密钥和多个应用,应用之间相互独立,并具有各自的管理员PIN、用户PIN 和权限。应用逻辑结构如图1所示。
图1 SKF设备的应用逻辑结构图
以数据加密调用过程为例,SKF 接口使用的一个典型流程如下:
(1)枚举设备:SKF_EnumDev
(2)连接设备:SKF_ConnectDev
(3)枚举应用:SKF_EnumApplication
(4)打开应用:SKF_OpenApplication
(5)验证应用PIN 码:SKF_VerifyPIN(6)枚举容器:SKF_EnumContainer
(7)打开容器:SKF_OpenContainer
(8)设置会话密钥:SKF_SetSymmKey
(9)加密初始化:SKF_EncryptInit
(10)加密多个数据包:SKF_EncryptUpdate
(11)加密多个数据包结束:SKF_EncryptFinal
(12)关闭容器:SKF_CloseContainer
(13)关闭应用:SKF_CloseApplication
(14)断开设备连接:SKF_DisConnectDev
公钥密码标准PKCS(Public-Key Cryptography Standards)是RSA 实验室与本行业、学术界以及政府的代表一起合作推出的一套规范,它包含一系列规范,其中PKCS#11 是加密设备接口标准。该标准详细规定了密码令牌接口Cryptoki(Cryptographic Token Interface)的编程接口,现在由OASIS(Organization for the Advancement of Structured Information Standards,结构化信息标准促进组织)技术委员会管理,最新的正式版本是2.40。
PKCS#11 定义了会话(session)、槽(slot)、令牌(token)、对象(object)的概念,用于抽象密码设备的使用过程。其中会话抽象应用与设备的连接,槽抽象卡槽或读卡器等安全设备,令牌抽象加密TF 卡等密码设备,对象抽象在密码操作中使用和产生各种数据结构[4]。
使用PKCS#11 标准的密码设备中,逻辑结构如图2 所示。
图2 PKCS#11设备的逻辑结构图
以数据加密调用过程为例,Cryptoki 使用的一个典型流程如下:
(1)初始化接口库:C_Initialize
(2)获取密码设备的槽位:C_GetSlotList
(3)选择使用的槽位,创建会话:C_OpenSession
(4)登录设备:C_Login
(5)查找已有的密钥或生成新密钥:
①查找初始化:C_FindObjectsInit
②进行查找:C_FindObjects
③结束查找:C_FindObjectsFinal
④生成:C_GenerateKey 或C_GenerateKeyPair
(6)加密初始化:C_EncryptInit
(7)加密多个数据包:C_EncryptUpdate
(8)加密多个数据包结束:C_EncryptFinal
(9)退出登录:C_Logout
(10)关闭会话:C_CloseSession
(11)退出库调用状态:C_Finalize
SKF 和PKCS#11 均是密码设备对外提供的接口标准,为外部开发者调用密码设备提供统一的、便利的途径。本节对两种接口的差异进行比较。
在SKF 标准中,权限分为设备权限、用户权限和管理员权限。在特定操作中(包括创建应用、删除应用和修改设备认证密钥),需要设备权限。在SKF 设备中,每个应用都有自己的PIN 码(包括用户PIN 码和管理员PIN 码),因此,各应用可独立地使用设备,获取权限。
在PKCS#11 中,没有设备权限,仅有用户权限和管理员权限。设备上仅有一个用户PIN 和一个管理员PIN。因此,当一个应用使用正确的PIN 码登录后,即通过了整个设备的权限认证。
对于SKF 设备,应用在开始使用时需要在设备中创建好相应的应用。因此,在正确枚举出设备后,应用可能涉及到的操作包括:设备认证、创建应用、打开应用、验证PIN 码(创建容器需要用户权限)、创建容器。之后,可以此容器中进行密钥操作和调用密码算法。
相对地,对于PKCS#11 设备,应用在正确枚举到设备后,需要的操作包括打开会话和登录。之后即可进密钥操作和调用密码算法。
SKF 接口通过应用和容器来组织密钥。在同一个设备中,可存在多个应用,而每个应用各自拥有若干个容器。一个容器可存放一对加密公私钥对和一对签名公私钥对,以及对应的加密证书和签名证书。在这些公私钥对和证书生成或导入后,设备将它们保存起来,直到通过接口函数将它们删除。在设备使用过程中产生的会话密钥,仅在会话期间有效。当会话关闭(如关闭容器)后,这些会话密钥不会保存。因此,SKF 接口中,以非对称密钥和会话密钥的操作为主,不支持对称密钥的存储。其他数据可作为文件存储于应用中,通过SKF 的文件操作相关接口来进行读写和控制。
相对地,PKCS#11 没有应用和容器的概念。它通过定义多种对象来组织密码设备上的数据,包括数据对象、证书对象和密钥对象[5]。PKCS#11 为每类对象定义了丰富详细的属性参数,使开发者可根据需求定义每个对象的属性,例如是否在设备中保存、对象的标识、是否可导出、是否可用于加解密、是否可用于打包其他密钥,等等。在应用调用PKCS#11 过程中,通过会话(session)来管理临时产生的对象。在一个session中产生的临时对象(session object),仅在此会话中可以使用。当此session 关闭时,这些对象都将消失。而保存于设备上的对象,所有应用都有同样的权限。
SKF 接口以支持国密算法为主,包括SM1、SM2、SM3、SM4,同时包括部分国际算法:RSA、SHA1 和SHA256。PKCS#11 支持多种国际算法,但可通过自定义机制进行扩展。
当前,部分密码设备提供PKCS#11 接口,不提供SKF 接口。在这种情况下,由于PKCS#11 接口更具普遍性,将PKCS#11 作为较低一层,可以实现SKF 接口,扩大密码设备的适用范围。
基于PKCS#11 实现SKF 接口,主要需要解决上节中分析的SKF 与PKCS#11 的差异处。PKCS#11 对象中丰富的属性,可用于建立与SKF 类似的应用结构。
在调用SKF 接口时,为找到可用的设备,设备管理类的函数往往最先调用,主要包括枚举设备、连接设备、断开设备、获取设备状态等)。对应到PKCS#11 接口中,可在此阶段进行库的初始化,查找设备和获取设备信息。可通过C_Initialize、C_GetSlotList 等接口获取。
由于SKF 和PKCS#11 中的权限管理不同,在这个阶段中,除了进行初始化,可完成PKCS#11 设备的登录。此后不使用PKCS#11 设备上的PIN。例如,在连接设备时,在已知密码设备PKCS#11 的PIN 码的情况下,调用PKCS#11 的登录接口。
SKF 中设备认证密钥、应用、容器及文件,由于在PKCS#11 无对应的概念,可通过在PKCS#11 设备中存储为对象来实现。对应的层次及结构关系,通过PKCS#11 对象可定义的丰富的属性来实现。例如,可通过定义特定的CKA_APPLICATION 或CKA_LABEL来标识出设备认证密钥,如下:
类似地,应用、应用PIN、容器、文件、证书均使用PKCS#11 数据对象存储,容器中的密钥对应使用PKCS#11 密钥对象存储。可使用以下属性来建立关系。
●应用和应用PIN:在创建应用时,使用PKCS#11接口创建数据对象存储。可使用一个对象。使用CKA_APPLICATION 标识为SKF 相关对象。将接口中传入的应用名称(szAppName)存入CKA_LABEL。PIN和PIN 的剩余可用次数及权限控制作为对象值写入。
●容器:创建容器时,使用PKCS#11 接口创建数据对象存储。使用CKA_APPLICATION 标识为某应用的容器。CKA_LABEL 中存储容器名称。
●文件:创建文件时,使用PKCS#11 接口创建数据对象存储。使用CKA_APPLICATION 标识为某应用的文件。CKA_LABEL 中存储文件名称。其他内容,包括文件大小,读写权限及文件内容存入CKA_VALUE 中。
●证书:在证书导入时,使用PKCS#11 接口创建数据对象存储。使用CKA_APPLICATION 存储应用名、容器名及证书标识。CKA_LABEL 中存储证书类型(加密证书或签名证书)。证书内容存入CKA_VALUE中。
●密钥:在密钥产生时,使用PKCS#11 接口创建密钥对象存储。使用CKA_ID 存储应用名、容器名、密钥类型(加密密钥或签名密钥)。
随着密码设备的广泛使用,使用统一的、标准的密码设备接口越来越关键。SKF 和PKCS#11 接口标准作为两种主流接口,很好地解决了这个问题,增强了应用程序的可移植性。本文对比分析了两种标准的差异性,并提出基于PKCS#11 实现SKF 的一种方案,为使用SKF 和PKCS#11 的开发人员提供参考。