我正在尝试从系统商店加载证书。我正在使用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);
为什么我需要将CERT_RDN_ATTR
的dwValueType设置为CERT_RDN_PRINTABLE_STRING
而不是CERT_RDN_UNICODE_STRING
? (我使用的是Unicode。)使用CERT_RDN_UNICODE_STRING
时,此代码不起作用。
尽管如此,我无法加载包含空格和俄语符号的主题CN的证书。对于简单的CN名称,例如“foo”,此代码非常完美。
如何以这种方式加载带有unicode名称的证书?
答案 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对您没有多大用处。