1

我正在尝试从系统存储加载证书。我正在使用CertFindCertificateInStoreCryptoAPI 中的函数:

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. 为什么我需要将 dwValueType 设置为CERT_RDN_ATTRtoCERT_RDN_PRINTABLE_STRING而不是CERT_RDN_UNICODE_STRING?(我使用的是 Unicode。)使用CERT_RDN_UNICODE_STRING此代码不起作用。

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

我该怎么做才能以这种方式加载具有 unicode 名称的证书?

4

2 回答 2

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 ant 结果,那个类型是 CERT_RDN_T61_STRING。然后我将 subjCN.dwValueType 设置为 CERT_RDN_T61_STRING 代码有效。对于俄罗斯符号,我需要 CERT_RDN_UNICODE_STRING。因此,如果您不知道证书中此属性的确切编码,那么带有 CERT_FIND_SUBJECT_ATTR 或 CERT_FIND_ISSUER_ATTR 的 CertFindCertificateInStore 对您没有多大用处。

于 2011-09-15T06:46:39.980 回答
1

如果你能从 MSDN 文档的乱七八糟的东西中理解任何东西,那你就太棒了。也许可以解构以下宝石以获得一些照明:

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

我猜“要匹配的字符串”在你的subjCN.Value.pbData领域。你用这个转换了X509_UNICODE_NAME吗?这似乎是您在CryptEncodeObject函数中所做的事情。去那个页面让我头疼。抱歉,您必须成为承受后续步骤的人。

于 2011-09-15T01:13:56.167 回答