CSP加密服务提供者(Cryptographic Service Provider)具有一下几个特点:
- CSP是真正执行密码运算的独立模块
- 物理上一个CSP由两部分组成:一个动态连接库,一个签名文件
- 签名文件保证密码服务提供者经过了认证,以防出现攻击者冒充CSP
- 若加密算法用硬件实现,则CSP还包括硬件装置
- Microsoft通过捆绑RSA Base Provider,在操作系统中提供一个CSP,使用RSA公司的公钥加密算法,更多的CSP可以根据需要增加到应用中。
- Windows 2000以后自带了多种不同的CSP
一、CSP服务体系
CSP服务体系分层
CSP服务体系从系统结构,系统调用层次方面来看,分为相互独立的三层(如上图:服务分层体系):
1)最底层是加密服务提供层,即具体的一个CSP,它是加密服务提供机构提供的独立模块,担当真正的数据加密工作,包括使用不同的加密和签名算法产生密钥,交换密钥、进行数据加密以及产生数据摘要、数字化签名它是独立于应用层和操作系统,其提供的通用的SPI编程接El与操作系统层进行交互;有些CSP使用特殊硬件一起担当加密工作,而有些则通过RPC分散其功能,以达到更为安全。
2)中间层,即操作系统(0S)层,在此是指具体的Win9X、NT和2K及更高版本的32位操作平台,在CSP体系中,以及为应用层提供统一的API接口,为加密服务提供层提供SPI接口,操作系统层为应用层隔离了底层CSP和具体加密实现细节,用户可独立各个CSP进行交互它担当一定管理功能,包括定期验证CSP等。
3)应用层,也就是任意用户进程或线程具体通过调用操作系统层提供的Crypto API使用加密服务的应用程序。
根据CSP服务分层体系,应用程序不必关心底层CSP的具体实现细节,利用统一的API接口进行编程,而由操作系统通过统一的SPI接口来与具体的加密服务提供者进行交互,由其他的厂商根据服务编程接口SPI实现加密、签名算法,有利于实现数字加密与数字签名。
应用程序中要实现数字加密与数字签名时,一般是调用微软提供的应用程序编程接口Crypto API。应用程序不能直接与加密服务提供者(CSP)通信,只能通过Crypto API操作系统界面过滤后,经过Crypto SPI系统服务接口与相应的CSP通信。CSP才是真正实现所有加密操作的独立模块。
二、CSP组成
CSP为Windows平台上加解密运算的最核心层实现,是真正执行加密工作的独立的模块。CSP与Windows的接口以DLL形式实现,CSP是真正执行加密工作的独立模块。
按照CSP的不同实现方法,可分为纯软件实现与带硬件的实现,其中带硬件的实现CSP按照硬件芯片不同,可以分为使用智能卡芯片(内置加密算法)的加密型和不使用智能卡芯片的存储型两种,与计算机的接口现在一般都用USB,所以把CSP硬件部分称为USB Key。
物理上一个CSP由这几部分组成:动态链接库,签名文件,签名文件保证提供者经过了认证,操作系统能识别CSP,操作系统可利用其定期验证CSP,保证其未被篡改。还可以使用辅助的DLL实现CSP,辅助的DLL不是CSP的一部分,但是包含CSP调用的函数,辅助的DLL也必须被签名,并且签名文件必须可用,每个DLL在装载库之前被验证签名,每个CSP都有一个名字和一个类型。若有硬件实现,则CSP还包括硬件装置。CSP逻辑上主要由以下部分组成(如图CSP组成):
(1)微软提供的SPI接口函数实现。在微软提供的SPI接口中共有23个基本密码系统函数由应用程序通过CAPI调用,CSP必须支持这些函数,这些函数提供了基本的功能。
(2)加密签名算法实现。如果是纯软件实现的CSP与用存储型的USB Key实现的CSP,这些函数就在CSP的DLL或辅助DLL中实现,带硬件设备实现的CSP,并且用加密型的USB Key,CSP的动态库就是一个框架,一般的函数实现是在CSP的动态库中,而主要函数的核心是在硬件中实现,在CSP的动态库中只是函数的框架,如:加/解密,散列数据,验证签名等,这是因为私钥一般不导出,这些函数的实现主要在硬件设备中,保密性好。
(3)CSP的密钥库及密钥容器,每一个加密服务提供程序都有一个独立的密钥库,它是一个CSP内部数据库,此数据库包含一个和多个分属于每个独立用户的容器,每个容器都用一个独立的标识符进行标识。不同的密钥容器内存放不同用户的签名密钥对与交换密钥对以及x.509数字证书。出于安全性考虑,私钥一般不可以被导出。带硬件实现的CSP,CSP的密钥库及密钥容器放在硬件存储器中,纯软的CSP实现是放在硬盘上的文件中。
三、CSP实现
在实现微软的CSP时采取了如上图所示:CSP设计框架。通过智能密码钥匙专用API实现了微软CSP。为了兼容NetScape浏览器等所支持的PKCS#11,在实现PKCS#ll的基础上,通过调用PKCS#ll接口实现微软CSP服务编程接口。这样在其它操作系统平台上实现PKCS时也就方便了很多。
用户界面获取PIN
当一个应用要求访问用户私钥或其他身份信息时,必须首先使用用户身份识别码(PIN)来认证用户,如图所示:用户界面获取PIN。通过了认证的程序允许访问身份密钥中的用户敏感数据。用户程序对身份密钥中用户敏感数据的访问必须在一个事务中完成。事务开始前,身份钥处于未认状态;事务结束后,身份密钥仍然返回未认证状态。为了避免每一次操作都要求用户输入PIN,应该在CSP内部缓存用PIN。所有关于用户PIN的显示和操作都必须从这个缓存中直接获得,并且这个缓存的PIN必须与特定登录用户和特定用户身份密钥同步关联,一旦登录用户改变或身份密钥从主机中取出,就必须清除相应的PIN缓存。
四、支持的CSP模块函数
中孚智能密码钥匙通过提供标准的CSP模块实现了与CryptoAPI应用程序无缝的集成。中孚智能密码钥匙的CSP模块是遵从微软的Crypto Service Provider编程规范编写,可以兼容现在和将来的CryptoAPI应用。次CSP是一个PROV_RSA_FULL类型的CSP,它具有一下特点:
提供了安全RSA密钥对容器
提供多种分组和Hash算法
硬件实现RSA运算
支持国产加密算法
编写的个人数字证书载体
以下所列是中孚智能密码钥匙支持的CSP模块函数,这些函数是CSP SPI,CryptoAPI应用程序不用直接调用这些接口,通过微软的安全体系间接调用。
名称 | 描述 |
连接函数 | |
CPAcquireContext | 为应用程序创建一个上下文 |
CPGetProvParam | 获取CSP相关信息 |
CPReleaseContext | 释放CPAcquireContext获取的上下文 |
CPGetProvParam | 设置CSP相关参数 |
密钥生成和交换函数 | |
CPDeriveKey | 从一个数据散列中生成一个会话密钥,保证生成的密钥互不相同 |
CPDestroyKey | 释放密钥句柄,释放后密钥句柄无效,密钥将不能再被访问 |
CPDuplicateKey | 创建密钥的拷贝 |
CPExportKey | 从CSP密钥容器中导出密钥 |
CPImportKey | 从一个Blob中导入密钥到CSP容器中 |
CPGenKey | 生成密钥或者密钥对 |
CPGenRandom | 生成随机数 |
CPSetKeyParam | 设置密钥属性 |
CPGetKeyParam | 获取密钥属性 |
CPGetUserKey | 获取密钥容器中持久密钥对 |
数据加密函数 | |
CPEncrypt | 加密明文 |
CPDecrypt | 解密密文 |
散列和数字签名函数 | |
CPCreateHash | 初始化散列对象 |
CPDestroyHash | 删除散列对象 |
CPDublicateHash | 创建散列对象拷贝 |
CPSetHashParam | 设置散列对象属性 |
CPGetHashParam | 获取散列对象属性 |
CPHashData | 散列输入数据 |
CPHashSessionKey | 散列一个会话密钥 |
CPSignHash | 签名一个散列对象 |
CPVerifySignature | 验证一个散列对象 |
CPAcquireContext函数是所有CSP函数中最先被调用的函数。上层应用通过调用这个函数来指定操作那一个密钥容器。每个密钥容器中同时只能保存一对RSA密钥对,和任意多个会话密钥。RSA密钥对是可以持久保存的对象,而会话密钥只能在运行时候存在。如果应用程序需要访问密钥容器中的RSA私钥,则中孚智能密钥钥匙的CSP将会要求验证用户的PIN码。将弹出验证用户PIN码的对话框。用户输入正确的PIN码,验证正确以后CSP模块将进行后续的操作。