CryptoAPI调用指南(二)

四、 证书操作

在CryptoAPI里,一般使用CERT_CONTEXT类型,即证书上下文,对数字证书进行操作,定义如下。
typedef struct _CERT_CONTEXT {
DWORD dwCertEncodingType;
BYTE *pbCertEncoded;
DWORD cbCertEncoded;
PCERT_INFO pCertInfo;
HCERTSTORE hCertStore;
} CERT_CONTEXT, *PCERT_CONTEXT
在这其中dwCertEncodingType是证书编码类型,常用值为X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;pbCertEncoded为证书数据;cbCertEncoded是数据长度字节数;pCertInfo是证书的各项属性信息,CERT_INFO的结构就不再贴了,大家可以自行查阅介绍,很容易懂;hCertStore是证书所在的证书库。
获得证书上下文的方法很多,下面介绍两种:

  • 从证书库里获得
    1.HCERTSTORE CertOpenStore(
    LPCSTR lpszStoreProvider,
    DWORD dwEncodingType,
    HCRYPTPROV_LEGACY hCryptProv,
    DWORD dwFlags,
    const void *pvPara
    )
    通过CertOpenStore方法打开一个证书库。lpszStoreProvider是证书库类型,最常用的几种设置值说明如下表:
说明
CERT_STORE_PROV_FILE从一个本地文件打开证书库,这个文件应该是一个序列化的证书库数据
CERT_STORE_PROV_MEMORY从缓存打开一个空白证书库。
CERT_STORE_PROV_PHYSICAL从指定的计算机上打开证书库。
CERT_STORE_PROV_PKCS7从PKCS7格式的签名信息里打开证书库。
CERT_STORE_PROV_REG从指定的注册表位置打开证书库。
CERT_STORE_PROV_SERIALIZED根据一个序列化的证书库数据打开证书库。
CERT_STORE_PROV_SYSTEM打开指定的证书库,这个证书库可以来自多台计算机(最常用)。
CERT_STORE_PROV_SYSTEM_REGISTRY从一个注册的计算机打开指定的证书库(在本地计算机使用情况下与CERT_STORE_PROV_SYSTEM相同)。

dwEncodingType没有实际用处,设置为0;hCryptProv指向一个CSP句柄,推荐传NULL,即使用默认CSP即可;dwFlags的低2字节部分定义了打开证书库的行为特性,如下表:

说明
CERT_STORE_CREATE_NEW_FLAG新建一个符合条件的证书库,如果这个证书库已存在就会失败。
CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG关闭证书库时会检查从库里返回的证书是否都被释放,只有全部释放了才会真正关闭证书库。
CERT_STORE_DELETE_FLAG删除要打开的证书库。
CERT_STORE_ENUM_ARCHIVED_FLAG把标记为存档(ARCHIVED)的证书也遍历处理。
CERT_STORE_MANIFOLD_FLAG将旧版本的证书存档。
CERT_STORE_NO_CRYPT_RELEASE_FLAG证书库关闭时不释放hCryptProv指定的CSP句柄。hCryptProv不为NULL时此设置有效。
CERT_STORE_OPEN_EXISTING_FLAG打开已经存在的证书库,如果证书库不存在,则失败。
CERT_STORE_READONLY_FLAG以只读方式打开证书库。
CERT_STORE_SET_LOCALIZED_NAME_FLAG为证书库设置本地名称。这个设置需要CSP支持,而且lpszStoreProvider是CERT_STORE_PROV_FILENAME,CERT_STORE_PROV_SYSTEM,CERT_STORE_PROV_SYSTEM_REGISTRY和CERT_STORE_PROV_PHYSICAL才有效。
CERT_STORE_UPDATE_KEYID_FLAG证书库里每个key的CERT_KEY_PROV_INFO_PROP_ID属性自动更新为key的标识值。

如果lpszStoreProvider是CERT_STORE_PROV_SYSTEM、CERT_STORE_PROV_SYSTEM_REGISTER或CERT_STORE_PROV_PHYSICAL,dwFlags的高2字节部分用于标识证书库所在位置。比如:
当前用户:CERT_SYSTEM_STORE_CURRENT_USER
本地计算机:CERT_SYSTEM_STORE_LOCAL_MACHINE
dwFlags的其他设置可以参考CryptoAPI手册。
CertOpenStore如果调用成功,则返回打开的证书库的句柄,否则返回NULL。
pvPara指向的数据和lpszStoreProvider有关,具体说明情况下表:

lpszStoreProviderpvPara
CERT_STORE_PROV_FILE文件句柄
CERT_STORE_PROV_MEMORY不需要设置
CERT_STORE_PROV_PHYSICAL证书库名+“\”+计算机名,比如Root.LocalMachine
CERT_STORE_PROV_PKCS7PKCS7格式的签名数据。
CERT_STORE_PROV_REG注册表键句柄。
CERT_STORE_PROV_SERIALIZED序列化的证书库数据。
CERT_STORE_PROV_SYSTEMUnicode或ASCII编码的证书库名称,比如MY或Root。
CERT_STORE_PROV_SYSTEM_REGISTRYUnicode或ASCII编码的证书库名称,比如MY或Root。

2.PCCERT_CONTEXT CertEnumCertificatesInStore(
HCERTSTORE hCertStore,
PCCERT_CONTEXT pPrevCertContext
)
调用此方法将返回证书库里的证书上下文。hCertStore是证书库句柄,由CertOpenStore返回;pPrevCertContext是前一个证书的证书上下文对象,如果传NULL,表示返回第一个证书上下文对象,否则返回排在pPrevCertContext下一个位置的证书的上下文对象;如果没有证书可以返回,此方法返回NULL。
通过循环调用CertEnumCertificatesInStore,即可实现对指定证书库的遍历。我们可以根据指定的条件,得遍历的结果进行查找过滤,得到需要的证书上下文或集合。
当返回的上下文对象不再使用时,应当调用CertFreeCertificateContext方法释放。
BOOL CertFreeCertificateContext(
PCCERT_CONTEXT pCertContext
)
pCertContext是要释放的上下文对象。

  • 根据证书数据直接生成
    有时我们已经从其他途径拿到了证书数据,此时就可以通过证书数据直接生成上下文对象。这种情况下,调用CertCreateCertificateContext方法即可。
    PCCERT_CONTEXT CertCreateCertificateContext(
    DWORD dwCertEncodingType,
    const BYTE *pbCertEncoded,
    DWORD cbCertEncoded
    )
    dwCertEncodingType为编码类型,老规矩,一般设置成X509_ASN_ENCODING | PKCS_7_ASN_ENCODING即可;pbCertEncoded是证书数据;cbCertEncoded是证书数据长度。注意,如果我们拿到的证书数据是BASE64格式的,那需要先将数据转换成二进制字节数组。方法调用成功会返回证书上下文对象,失败返回NULL,调用GetLastError返回具体错误信息。
    同样,上述方法返回的证书上下文对象使用完毕后,需要调用CertFreeCertificateContext方法释放。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_45303938

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值