在前面了解了CryptoAPI和CSP的相关概念之后,我们具体分析了CryptoAPI的相关函数,实现了写证书、私钥的过程和更新证书的过程。
写证书和私钥到CSP的方案:
首 先将CA返回给RA的证书和私钥进行封装,将它们封装成P12结构证书,然后将P12结构证书导入到一个临时的证书库中。在该临时库中找到证书的上下文, 通过证书上下文获得一个临时的CSP句柄和证书对应的私钥的类型,然后根据这个CSP句柄和私钥类型获得对应的私钥句柄。利用前面得到的CSP句柄和私钥 句柄将私钥以PRIVATEKEYBLOB的形式从CSP导出来。利用CryptAcquireContext函数创建一个密钥容器并获得USBKey CSP的句柄,然后将前面导出来的blob形式的私钥导入USBKey CSP的密钥容器中,同时获得了该密钥容器中的私钥的句柄。通过该私钥句柄将对应的证书写进密钥容器中,从而完成了证书和私钥的写入。
具体过程实现如下:
(1) 将CA返回给RA的证书和私钥进行封装,将它们封装成P12结构证书。
(2) 利用PFXImportCertStore函数将P12结构证书导入一个临时的内存型证书库,并获得该库的句柄hImportStore。
(3) 利用CertFindCertificateInStore函数获得hImportStore.证书库中的证书上下文pCertContext。
(4) 利用上面得到的证书上文pCertContext,通过CryptAcquireCertificatePrivateKey函数获得临时CSP句柄hCryptProv,证书对应私钥的类型dwKeySpec。
(5) 利用临时CSP句柄hCryptProv,私钥的类型dwKeySpec,通过CryptGetUserKey获得证书对应的私钥句柄hUserKey。
(6) 利用私钥句柄hUserKey,通过CryptExportKey将私钥以PRIVATEKEYBLOB的形式导出来,获得私钥的blob和长度。
(7) 通过CryptAcquireContext函数,创建密钥容器并获得USBKey CSP的句柄hProv。
(8) 利用获得hProv和上面获得的私钥blob和长度,通过CryptImportKey函数将私钥导进USBKey CSP中,并返回私钥句柄hKey。
(9) 利用私钥句柄hKey,和前面获得的证书上下文pCertContext的内容,通过CryptSetKeyParam函数将证书写进对应的密钥容器。
(10) 到此为止,已经实现了将证书和私钥写进USBKey CSP的过程。
证书更新的过程方案:
CA 将更新后的证书发给RA,RA用证书更新前的序列号去查找系统库中对应的证书,找到该证书之后,利用该证书上下文获得USBKey CSP句柄和密钥类型,从而获得要更新证书对应的私钥句柄。利用获得的私钥句柄,将更新的证书写入私钥对应的密钥容器中,从而完成证书更新过程。为了防止 系统库中有多个CA中心颁发的相同序列号的证书,在RA查找到了相同序列号的证书后,再将已经更新的证书和找到的证书的AKID(颁发者密钥标识符)进行 比较,如果两者相同,说明找到要更新的证书,如果没有,则继续查找。
具体实现的过程如下:
(1) 通过CryptAcquireContext函数获得USBKey CSP句柄hProv。
(2) 利用hProv,通过CertOpenStore函数打开系统库,获得系统库句柄hCertStore。
(3) 利用hCertStore,通过CertEnumCertificatesInStore函数枚举证书库中的证书上下文,获得了证书上下文 (pCertContext)后,取出对应的证书序列号与RA处给的序列号,如果相同,就再将更新的证书与这个证书上下文的AKID进行比较,如果仍然相 同,则认为找到要进行更新的证书。反之则继续查找。同时释放USBKey CSP句柄hProv。
(4) 利用pCertContext,通过CryptAcquireCertificatePrivateKey函数获得USBKey CSP句柄hProv,证书对应私钥的类型dwKeySpec。
(5) 利用临时CSP句柄hProv,私钥的类型dwKeySpec,通过CryptGetUserKey获得证书对应的私钥句柄hUserKey。
(6) 利用私钥句柄hUserKey和更新的证书,通过CryptSetKeyParam函数将更新证书写进对应的密钥容器。
(7) 至此,完成了证书更新的过程。
上面的开发平台是Win2000+VC.6.0。用微软的证书服务机构颁发的证书进行了上面方案的测试,写入的证书和私钥在安全web站点访问、安全电子邮件测试中均通过,说明该方案是可行的。
时间: 2024-11-10 13:04:44