Результат, к сожалению, пока отрицательный.
Симптомы таковы: запрос на сертификат успешно создаётся, CA возвращает сертификат.
НО! дополнительные атрибуты ключа, такие как CERT_NON_REPUDIATION_KEY_USAGE или CERT_DIGITAL_SIGNATURE_KEY_USAGE не устанавливаются. Аналогично и временные рамки валидности сертификата остаются "по-умолчанию" (??) - 1 год с даты выписки.
То есть получаемый сертификат одинаков - делаем мы эти "танцы с бубном" или нет) При этом, данные передаваемые в SERT_NAME_ARRAY (common name, locality и т.п.) благополучно устанавливаются, куда им и положено.
Ещё раз подчеркну. Рассматриваем процесс создания ЗАПРОСА на сертификат. Для взаимодействия с удалённым CA используем COM-компонент CertRequest.
???? М.б. на CA используется особый шаблон для этого интерфейса ????
Текущий код таков:
// fill CERT_PRIVATE_KEY_VALIDITY
FILETIME ftBegin(...), ftEnd(...);
CERT_PRIVATE_KEY_VALIDITY CertPrivateKeyValitity;
CertPrivateKeyValitity.NotBefore = ftBegin;
CertPrivateKeyValitity.NotAfter = ftEnd;
// fill CRYPT_BIT_BLOB
BYTE bRepudiation[2] = {(CERT_NON_REPUDIATION_KEY_USAGE | CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_DATA_ENCIPHERMENT_KEY_USAGE), 0};
CRYPT_BIT_BLOB CryptBitBlob;
CryptBitBlob.cbData = 2;
CryptBitBlob.pbData = bRepudiation;
CryptBitBlob.cUnusedBits = 0;
DWORD dwHashSize(0);
bReturn = CryptHashPublicKeyInfo(hCryptProv, CALG_SHA1, 0, PKCS_7_ASN_ENCODING, pbPublicKeyInfo, NULL, &dwHashSize);
BYTE* pbHashVal = new BYTE[dwHashSize];
bReturn = CryptHashPublicKeyInfo(hCryptProv, CALG_SHA1, 0, PKCS_7_ASN_ENCODING, pbPublicKeyInfo, pbHashVal, &dwHashSize);
// fill CRYPT_DATA_BLOB
CRYPT_DATA_BLOB CryptDataBlob;
CryptDataBlob.cbData = dwHashSize;
CryptDataBlob.pbData = pbHashVal;
// fill CERT_KEY_ATTRIBUTES_INFO
CERT_KEY_ATTRIBUTES_INFO CertKeyAttrInfo;
CertKeyAttrInfo.pPrivateKeyUsagePeriod = &CertPrivateKeyValitity;
CertKeyAttrInfo.IntendedKeyUsage = CryptBitBlob;
CertKeyAttrInfo.KeyId = CryptDataBlob;
DWORD cbKeyAttrEncoded(0);
bReturn = CryptEncodeObject(
PKCS_7_ASN_ENCODING // Encoding type
, X509_KEY_ATTRIBUTES // Structure type
, &CertKeyAttrInfo // Address of CERT_KEY_ATTRIBUTES_INFO structure
, NULL // pbEncoded
, &cbKeyAttrEncoded); // pbEncoded size
//-------------------------------------------------------------------
// Allocate memory for the encoded struct.
BYTE* pbKeyAttrEncoded(NULL);
pbKeyAttrEncoded = (BYTE*)malloc(cbKeyAttrEncoded);
//-------------------------------------------------------------------
// Call CryptEncodeObject to do the actual encoding of the struct.
bReturn = CryptEncodeObject(
PKCS_7_ASN_ENCODING // Encoding type
, X509_KEY_ATTRIBUTES // Structure type
, &CertKeyAttrInfo // Address of CERT_KEY_ATTRIBUTES_INFO structure
, pbKeyAttrEncoded // pbEncoded
, &cbKeyAttrEncoded); // pbEncoded size
// fill CRYPTOAPI_BLOB
CRYPT_OBJID_BLOB CryptObjidBlob;
CryptObjidBlob.cbData = cbKeyAttrEncoded;
CryptObjidBlob.pbData = pbKeyAttrEncoded;
CERT_EXTENSION CertExtension[] =
{
{
szOID_KEY_ATTRIBUTES,
TRUE,
CryptObjidBlob
}
};
CERT_EXTENSIONS CertExtensions;
CertExtensions.cExtension = 1;
CertExtensions.rgExtension = &CertExtension[0];
DWORD cbCertExtensionsEncoded(0);
bReturn = CryptEncodeObject(
PKCS_7_ASN_ENCODING // Encoding type
, X509_EXTENSIONS // Structure type
, &CertExtensions // Address of CERT_EXTENSIONS structure
, NULL // pbEncoded
, &cbCertExtensionsEncoded); // pbEncoded size
//-------------------------------------------------------------------
// Allocate memory for the encoded struct.
BYTE* pbCertExtensionsEncoded(NULL);
pbCertExtensionsEncoded = (BYTE*)malloc(cbCertExtensionsEncoded);
//-------------------------------------------------------------------
// Call CryptEncodeObject to do the actual encoding of the struct.
bReturn = CryptEncodeObject(
PKCS_7_ASN_ENCODING // Encoding type
, X509_EXTENSIONS // Structure type
, &CertExtensions // Address of CERT_EXTENSIONS structure
, pbCertExtensionsEncoded // pbEncoded
, &cbCertExtensionsEncoded); // pbEncoded size
////////////////////////////////////////////////////////////////////////
// fill CRYPTOAPI_BLOB
CRYPT_ATTR_BLOB AttributesBlobArr[] =
{
{
cbCertExtensionsEncoded,
pbCertExtensionsEncoded
}
};
// fill CRYPT_ATTRIBUTE
CRYPT_ATTRIBUTE CryptAttribute;
CryptAttribute.pszObjId = szOID_CERT_EXTENSIONS;
CryptAttribute.cValue = 1;
CryptAttribute.rgValue = AttributesBlobArr;
// fill CERT_REQUEST_INFO
CERT_REQUEST_INFO CertReqInfo;
CertReqInfo.Subject = SubjNameBlob;
CertReqInfo.cAttribute = 1;
CertReqInfo.rgAttribute = &CryptAttribute;
CertReqInfo.dwVersion = CERT_REQUEST_V1;
CertReqInfo.SubjectPublicKeyInfo = *pbPublicKeyInfo;
Далее вызывается CryptSignAndEncodeCertificate()