如何使用CryptoAPI加载带有unicode CN的证书?

时间:2011-09-14 08:00:01

标签: cryptography cryptoapi pfx

我正在尝试从系统商店加载证书。我正在使用CryptoAPI中的函数CertFindCertificateInStore

std::string certName;
CERT_RDN_ATTR subjCN;
subjCN.pszObjId = szOID_COMMON_NAME;
subjCN.dwValueType = CERT_RDN_PRINTABLE_STRING;
subjCN.Value.cbData = 2*(certName.size()); 
subjCN.Value.pbData = (BYTE*)certName.c_str();
CERT_RDN rdn;
rdn.cRDNAttr = 1;
rdn.rgRDNAttr = &subjCN;

cert = CertFindCertificateInStore ( certStore,    
                                    X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                    CERT_UNICODE_IS_RDN_ATTRS_FLAG ,
                                    CERT_FIND_SUBJECT_ATTR,
                                    &rdn,
                                    NULL);
  1. 为什么我需要将CERT_RDN_ATTR的dwValueType设置为CERT_RDN_PRINTABLE_STRING而不是CERT_RDN_UNICODE_STRING? (我使用的是Unicode。)使用CERT_RDN_UNICODE_STRING时,此代码不起作用。

  2. 尽管如此,我无法加载包含空格和俄语符号的主题CN的证书。对于简单的CN名称,例如“foo”,此代码非常完美。

  3. 如何以这种方式加载带有unicode名称的证书?

2 个答案:

答案 0 :(得分:1)

如果您能从MSDN文档的乱码中了解任何内容,那么您就会感到惊讶。也许下面的宝石可以被解构为一些照明:

  

CERT_UNICODE_IS_RDN_ATTRS_FLAG dwFindFlags值仅用于   CERT_FIND_SUBJECT_ATTR和CERT_FIND_ISSUER_ATTR值   dwFindType。如果是,则必须设置CERT_UNICODE_IS_RDN_ATTRS_FLAG   pvFindPara指向的CERT_RDN_ATTR结构已初始化为   Unicode字符串。在进行任何比较之前,字符串是   匹配是使用X509_UNICODE_NAME转换为Unicode   比较。

我想“要匹配的字符串”位于subjCN.Value.pbData字段中。您是否使用X509_UNICODE_NAME转换了此内容?这似乎是你在CryptEncodeObject函数中所做的事情。去那个页面让我头疼。对不起,你必须成为下一步的受害者。

答案 1 :(得分:1)

我更仔细地查看了文档。据我了解, 证书名称blob包含rdn属性的编码数组 http://msdn.microsoft.com/en-us/library/aa382005(v=vs.85).aspx 每个rdn属性都有类型 - 例如UTF8,UNICODE,T.61等。

对CertFindCertificateInStore使用CERT_UNICODE_IS_RDN_ATTRS_FLAG时,此函数转换为支持的字符串 在RDN属性中从Unicode到RDN属性类型,然后将此值与证书RDN的匹配。

所以我用CryptDecodedObject解码了我的证书,看了RDN Common Name,结果证明,那个类型是CERT_RDN_T61_STRING。然后我将subjCN.dwValueType设置为CERT_RDN_T61_STRING代码已经工作。对于俄罗斯符号,我需要CERT_RDN_UNICODE_STRING。 因此,如果您不知道证书中此属性的确切编码,那么带有CERT_FIND_SUBJECT_ATTR或CERT_FIND_ISSUER_ATTR的CertFindCertificateInStore对您没有多大用处。