Добавление альтернативного имени субъекта в самозаверяющий сертификат с помощью wincrypt
Как добавить альтернативное имя субъекта в сертификат. Используя wincrypt, я создал и добавил сертификат в "MY" и "root" путь, где CN может быть полным доменным именем, именем хоста или IP. В качестве альтернативного имени субъекта я хочу добавить следующее:DNS-имя = полное доменное имя, DNS-имя = имя хоста и DNS-имя =IP. Как это сделать? Я не хочу использовать openssl.
LPCTSTR cnName= fqdn;
DWORD cbEncoded = 0;
if (!CertStrToName(X509_ASN_ENCODING, cnName, CERT_X500_NAME_STR, NULL,
pbdata, &cbData, NULL))
{
_tprintf(_T("CertStrToName failed 0x%x\n"), GetLastError());
return 0;
}
if (!(pbdata = (BYTE *)malloc(cbData)))
{
_tprintf(_T("malloc Error 0x%x\n"), GetLastError());
return 0;
}
if (!CertStrToName(X509_ASN_ENCODING, cnName, CERT_X500_NAME_STR, NULL, pbdata, &cbData, NULL))
{
_tprintf(_T("CertStrToName failed 0x%x\n"), GetLastError());
return 0;
}
CERT_NAME_BLOB IssuerBlob;
IssuerBlob.cbData = cbEncoded;
IssuerBlob.pbData = pbEncoded;
CertCreateSelfSignCertificate(NULL, &IssuerBlob, 0, &KeyProvInfo, &Alg, 0, &EndTime, 0);
OpenandAddCertificateToStore(pCertContext, L"MY");
OpenandAddCertificateToStore(pCertContext, L"Root");
Это создает и добавляет сертификат в хранилище без SAN в сертификате
Я попытался передать список расширений, как показано ниже:
CertCreateSelfSignCertificate(NULL, &IssuerBlob, 0, &KeyProvInfo, &Alg, 0, &EndTime, &myExtns_list);
CERT_EXTENSION myExtn;
myExtn.fCritical = TRUE;
myExtn.pszObjId = szOID_SUBJECT_ALT_NAME;
myExtn.Value = myBlobdata;
CERT_EXTENSIONS myExtns_list;
myExtns_list.cExtension = 1;
myExtns_list.rgExtension = &myExtn;
char cb[20] = { "DNS Names=abc.com" };
BYTE *pbData = (BYTE*)cb;
CERT_NAME_BLOB myBlobdata;
myBlobdata.cbData = 20;
myBlobdata.pbData = pbData;
с этим я мог получить SAN как формат байта на левой панели, а на правой панели отображается моя строка "DNS Names=abc.com".
Но мое требование - показывать только имена DNS в сети SAN.
1 ответ
Я предполагаю, что ваше создание данных расширения действительно произошло до вашего звонка CertCreateSelfSignedCertificate
(и, кроме того, что ваше здание myBlobdata
произошло до его использования).
Основная проблема заключается в том, что вы использовали одну запись SAN (вроде) в качестве полного расширения SAN; что означало, что вы потеряли некоторые обертки для кодирования. Вторая проблема заключается в том, что вы использовали szOID_SUBJECT_ALT_NAME
, который является неправильным OID для альтернативного имени субъекта... вы на самом деле хотите szOID_SUBJECT_ALT_NAME2
,
Я хочу добавить следующее:DNS-имя = полное доменное имя, DNS-имя = имя хоста и DNS-имя = IP
Добавление IP-адреса в качестве DNS-имени нестандартно и может привести к ошибке сопоставления. Вы действительно хотите добавить IP-адрес в качестве записи IP-адреса SAN.
CERT_ALT_NAME_ENTRY entries[3];
entries[0] = { CERT_ALT_NAME_DNS_NAME };
entries[0].pwszDNSName = L"example.org";
// IPv4 Address 10.12.1.130
BYTE ip4Bytes[] = { 10, 12, 1, 130 };
entries[1] = { CERT_ALT_NAME_IP_ADDRESS };
entries[1].IPAddress = { sizeof(ip4Bytes), ip4Bytes };
// ::1, big-endian
BYTE ip6Bytes[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
entries[2] = { CERT_ALT_NAME_IP_ADDRESS };
entries[2].IPAddress = { sizeof(ip6Bytes), ip6Bytes };
CERT_NAME_BLOB name = { cbEncoded, buf };
BYTE extBuf[1024] = { 0 };
cbEncoded = sizeof(extBuf);
CERT_ALT_NAME_INFO info = { sizeof(entries) / sizeof(CERT_ALT_NAME_ENTRY), entries };
if (!CryptEncodeObjectEx(
X509_ASN_ENCODING,
X509_ALTERNATE_NAME,
&info,
0,
nullptr,
extBuf,
&cbEncoded))
{
// Whatever your error handling story is.
//
// Note I didn't do a 0 buffer or CRYPT_ENCODE_ALLOC; I just knew
// that my buffer would be big enough.
}
CERT_EXTENSION extension = { 0 };
extension.fCritical = 0;
extension.pszObjId = szOID_SUBJECT_ALT_NAME2;
extension.Value = { cbEncoded, extBuf };
CERT_EXTENSIONS extensions = { 1, &extension };
...
PCCERT_CONTEXT cert = CertCreateSelfSignCertificate(
0,
&name,
0,
&keyProvInfo,
&sigAlg,
0,
&certExpirationDate,
&extensions);
В CertUI это дает мне значение Subject Alternative Name, которое я ожидаю:
DNS Name=example.org
IP Address=10.12.1.130
IP Address=0000:0000:0000:0000:0000:0000:0000:0001