Статус: Активный участник
Группы: Участники
Зарегистрирован: 17.10.2008(UTC) Сообщений: 70
|
Уж не знаю. Я, пожалуй, выложу код. Может будет возможность глянуть и сказать, что не так. Код:
int CCryptographicManager::CreateKeyAndCertificate(CString sFile, CString sPassword, TCertInfo &certInfo, bool bSelfSigned)
{
int num;
WORD wBits = 0, wMonths = 0;
DWORD dwUsage = 0, dwKeyType = AT_KEYEXCHANGE;
bool bSubjectUser = true;
bool bIssuerUser = true;
SYSTEMTIME sysTD;
FILETIME udcTimeBefore, udcTimeAfter;
BOOL bReturn = FALSE;
BOOL bResult;
LPBYTE pbNameBlob = NULL;
LPSTR szContainer = NULL;
HCRYPTPROV hProv = 0;
HCRYPTPROV hIssuerProv = 0;
HCRYPTPROV hCryptProvCA = 0;
HCRYPTKEY hPubKey = 0;
HCRYPTKEY hSessionKey = 0;
HCRYPTKEY hPrKey= 0;
HCRYPTHASH hHash = 0;
HCERTSTORE hStore = 0;
HANDLE hCertFile = INVALID_HANDLE_VALUE;
HANDLE hKeyFile = INVALID_HANDLE_VALUE;
PCRYPT_DATA_BLOB KeyId = NULL;
PCERT_PUBLIC_KEY_INFO PublicKeyInfo = NULL;
PCCERT_CONTEXT pIssuerCert = NULL;
PCCERT_CONTEXT pCertContext = NULL;
LPBYTE pbKeyIdentifier = NULL;
LPBYTE SubjectKeyIdentifier = NULL;
LPBYTE pbKeyUsage = NULL;
LPBYTE pbEnhKeyUsage = NULL;
LPBYTE pbBasicConstraints = NULL;
LPBYTE pbAuthorityKeyId = NULL;
LPBYTE bpEncodedCert = NULL;
LPBYTE pbExportedKey = NULL;
LPBYTE pbExtEncodedRole = NULL;
PCRYPT_KEY_PROV_INFO KeyProvInfo = 0;
CERT_ENHKEY_USAGE CertEnhKeyUsage = { 0, NULL };
BYTE SerialNumber[8];
CERT_BASIC_CONSTRAINTS2_INFO BasicConstraints;
CERT_AUTHORITY_KEY_ID_INFO AuthorityKeyId;
BYTE ByteData;
CRYPT_BIT_BLOB KeyUsage;
CERT_EXTENSION CertExtension[5];
CRYPT_DATA_BLOB CertKeyIdentifier;
CERT_NAME_BLOB IssuerName;
HANDLE hHeap = GetProcessHeap();
CERT_INFO CertInfo;
DWORD dwSize, m, q;
DWORD dwAcquireFlags, dwIssuerKeyType = 0;
DWORD dwIssuerFlags, dwSubjectFlags;
CHAR szProvider[260] = { MS_DEF_PROV };
DWORD dwProviderType = PROV_RSA_FULL;
BOOL bAddAuthorityExtension = FALSE;
DWORD cbExtEncodedRole;
WCHAR *unicodeConvertedString;
USES_CONVERSION;
/************************************************************************/
/* */
/************************************************************************/
// дополнительная инфорамция
const int nConstAttrCount = 7;
int nAttrCount = 0;
CERT_RDN_ATTR rgNameAttr[nConstAttrCount];
{
nAttrCount = 0;
// полное имя
unicodeConvertedString = T2W(certInfo.sCommonName.GetBuffer());
certInfo.sFullName.ReleaseBuffer();
rgNameAttr[nAttrCount].dwValueType = CERT_RDN_UNICODE_STRING;
rgNameAttr[nAttrCount].pszObjId = szOID_COMMON_NAME;
rgNameAttr[nAttrCount].Value.cbData = strlen(certInfo.sCommonName)*2;
rgNameAttr[nAttrCount++].Value.pbData = (BYTE*)(unicodeConvertedString);
// электронаня почта
unicodeConvertedString = T2W(certInfo.sMail.GetBuffer());
certInfo.sFullName.ReleaseBuffer();
rgNameAttr[nAttrCount].dwValueType = CERT_RDN_UNICODE_STRING;
rgNameAttr[nAttrCount].pszObjId = szOID_RSA_emailAddr;
rgNameAttr[nAttrCount].Value.cbData = strlen(certInfo.sMail)*2;
rgNameAttr[nAttrCount++].Value.pbData = (BYTE*)(unicodeConvertedString);
// организация
unicodeConvertedString = T2W(certInfo.sOrganization.GetBuffer());
certInfo.sFullName.ReleaseBuffer();
rgNameAttr[nAttrCount].dwValueType = CERT_RDN_UNICODE_STRING;
rgNameAttr[nAttrCount].pszObjId = szOID_ORGANIZATION_NAME;
rgNameAttr[nAttrCount].Value.cbData = strlen(certInfo.sOrganization)*2;
rgNameAttr[nAttrCount++].Value.pbData = (BYTE*)(unicodeConvertedString);
// подразделение
unicodeConvertedString = T2W(certInfo.sDevision.GetBuffer());
certInfo.sFullName.ReleaseBuffer();
rgNameAttr[nAttrCount].dwValueType = CERT_RDN_UNICODE_STRING;
rgNameAttr[nAttrCount].pszObjId = szOID_ORGANIZATIONAL_UNIT_NAME;
rgNameAttr[nAttrCount].Value.cbData = strlen(certInfo.sDevision)*2;
rgNameAttr[nAttrCount++].Value.pbData = (BYTE*)(unicodeConvertedString);
// город
unicodeConvertedString = T2W(certInfo.sTown.GetBuffer());
certInfo.sFullName.ReleaseBuffer();
rgNameAttr[nAttrCount].dwValueType = CERT_RDN_UNICODE_STRING;
rgNameAttr[nAttrCount].pszObjId = szOID_LOCALITY_NAME;
rgNameAttr[nAttrCount].Value.cbData = strlen(certInfo.sTown)*2;
rgNameAttr[nAttrCount++].Value.pbData = (BYTE*)(unicodeConvertedString);
// область
unicodeConvertedString = T2W(certInfo.sRegion.GetBuffer());
certInfo.sFullName.ReleaseBuffer();
rgNameAttr[nAttrCount].dwValueType = CERT_RDN_UNICODE_STRING;
rgNameAttr[nAttrCount].pszObjId = szOID_STATE_OR_PROVINCE_NAME;
rgNameAttr[nAttrCount].Value.cbData = strlen(certInfo.sRegion)*2;
rgNameAttr[nAttrCount++].Value.pbData = (BYTE*)(unicodeConvertedString);
// страна
unicodeConvertedString = T2W(certInfo.sCountry.GetBuffer());
certInfo.sFullName.ReleaseBuffer();
rgNameAttr[nAttrCount].dwValueType = CERT_RDN_UNICODE_STRING;
rgNameAttr[nAttrCount].pszObjId = szOID_COUNTRY_NAME;
rgNameAttr[nAttrCount].Value.cbData = strlen(certInfo.sCountry)*2;
rgNameAttr[nAttrCount++].Value.pbData = (BYTE*)(unicodeConvertedString);
}
CERT_RDN rgRDN[nConstAttrCount]=
{
{1, &rgNameAttr[0]},
{1, &rgNameAttr[1]},
{1, &rgNameAttr[2]},
{1, &rgNameAttr[3]},
{1, &rgNameAttr[4]},
{1, &rgNameAttr[5]},
{1, &rgNameAttr[6]},
};
CERT_NAME_INFO Name = {nConstAttrCount, &rgRDN[0]};
if(CryptEncodeObject(
(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), // Encoding type
X509_NAME, // Structure type
&Name, // Address of CERT_NAME_INFO structure
NULL, // pbEncoded
&dwSize)) // pbEncoded size
{
printf("The first call to CryptEncodeObject succeeded. \n");
}
else
{
printf("First call to CryptEncodeObject failed.\
\nA public/private key pair may not exit in the container. \n");
ShowError(GetLastError());
}
//-------------------------------------------------------------------
// Allocate memory for the encoded name.
if(!(pbNameBlob = (BYTE*)malloc(dwSize)))
printf("pbNamencoded malloc operation failed.\n");
//-------------------------------------------------------------------
// Call CryptEncodeObject to do the actual encoding of the name.
if(CryptEncodeObject(
(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), // Encoding type
X509_NAME, // Structure type
&Name, // Address of CERT_NAME_INFO structure
pbNameBlob, // pbEncoded
&dwSize)) // pbEncoded size
{
printf("The object is encoded. \n");
}
else
{
free(pbNameBlob);
printf("Second call to CryptEncodeObject failed.\n");
}
IssuerName.cbData = dwSize;
IssuerName.pbData = pbNameBlob;
/************************************************************************/
/* */
/************************************************************************/
if (bSubjectUser)
{
/* Certificate will be in the User store and*/
/* key container will be a User container*/
dwAcquireFlags = 0;
dwSubjectFlags = CERT_SYSTEM_STORE_CURRENT_USER;
dwSubjectFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
}
if (bIssuerUser)
{
/* Get Issuer Certificate from User store*/
dwIssuerFlags = CERT_SYSTEM_STORE_CURRENT_USER;
}
else
{
/* Get Issuer Certificate from Machine store*/
dwIssuerFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
}
/* Convert Enhanced Key usage number to*/
/* Enhanced Key Usage extension*/
/* Find Enhanced Key Usage extensions count*/
for (m = 0; m < g_EnhKeyUsage.dwCount; m++)
{
if ((g_EnhKeyUsage.dwValue[m] & dwUsage) == g_EnhKeyUsage.dwValue[m])
{
CertEnhKeyUsage.cUsageIdentifier++;
}
}
/* If extensions exist continue*/
if (CertEnhKeyUsage.cUsageIdentifier != 0)
{
/* Allocate memory for Enhanced Key Usage array*/
CertEnhKeyUsage.rgpszUsageIdentifier =
(LPSTR *)HeapAlloc(hHeap, 0, CertEnhKeyUsage.cUsageIdentifier * sizeof(LPSTR));
if (!CertEnhKeyUsage.rgpszUsageIdentifier)
{
printf("Unable to allocate memory for Enhanced Usage array\n");
return false;
}
/* Initialize Enhanced Key Usage array to NULL*/
for (m = 0; m < CertEnhKeyUsage.cUsageIdentifier; m++)
{
CertEnhKeyUsage.rgpszUsageIdentifier[m] = NULL;
}
/* Add proper extension OID to array*/
q = 0;
for (m = 0; m < g_EnhKeyUsage.dwCount; m++)
{
if ((g_EnhKeyUsage.dwValue[m] & dwUsage) == g_EnhKeyUsage.dwValue[m])
{
CertEnhKeyUsage.rgpszUsageIdentifier[q++] = g_EnhKeyUsage.szUsage[m];
}
}
}
//загрузка закрытого ключа центра сертификации для подписи
BYTE* pbData= NULL;
int iDataLen = 0;
// тут пока просто зашитый ключ УЦ
iDataLen= _CurKeyBlob.GetLength()/2;
pbData= new BYTE [iDataLen+1];
LPTSTR szPKBitStr= _CurKeyBlob.GetBuffer(_CurKeyBlob.GetLength());
StrToByte(_PrvKeyBlob.GetLength(), szPKBitStr, pbData);
_CurKeyBlob.ReleaseBuffer();
//Создание (получение) контекста и контейнера ключей по умолчанию с именем TempKey для кодирования ключа
szContainer = "TempKeyCA";
if(!CryptAcquireContext(&hCryptProvCA, szContainer, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
{
if(!CryptAcquireContext(&hCryptProvCA, szContainer, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET/**/))
{
HandleError(_T("Ошибка при вызове CryptAcquireContext для ключа подписи."));
}
else
TRACE0(_T("КРИПТОГРАФИЧЕСКИЙ КОНТЕКСТ СОЗДАН\n"));
}
else
TRACE0(_T("КРИПТОГРАФИЧЕСКИЙ КОНТЕКСТ ПОЛУЧЕН\n"));
if(!bSelfSigned)
{
//Загрузка закрытого ключа.
if(!CryptImportKey(hCryptProvCA, pbData, iDataLen, 0, CRYPT_EXPORTABLE, &hPrKey))
{
ShowError(GetLastError());
}
}
/* Create new crypto context*/
szContainer = "TempKey";
if(!CryptAcquireContext(&hProv, szContainer, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
if(!CryptAcquireContext(&hProv, szContainer, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET))
{
ShowError(GetLastError());
return false;
}
else
TRACE0(_T("КРИПТОГРАФИЧЕСКИЙ КОНТЕКСТ СОЗДАН\n"));
else
TRACE0(_T("КРИПТОГРАФИЧЕСКИЙ КОНТЕКСТ ПОЛУЧЕН\n"));
/* Generate Private/Public key pair*/
bResult = CryptGenKey(hProv, dwKeyType, CRYPT_EXPORTABLE+(wBits<<16), &hPubKey);
if (!bResult)
{
printf("CryptGenKey failed with %x\n", GetLastError());
return false;
}
/* Zero CERT_INFO structure*/
ZeroMemory(&CertInfo, sizeof(CertInfo));
/* Set Version of Certificate*/
CertInfo.dwVersion = CERT_V3;
/* Create Random Serial Number*/
bResult = CryptGenRandom(hProv, 8, SerialNumber);
if (!bResult)
{
printf("CryptGenRandom failed with %x\n", GetLastError());
return false;
}
// запоминаем серийный номер
int iSNLen= 2*8 + 1;
LPTSTR szSerialNumber = new char[iSNLen];
ByteToStr(8, SerialNumber, szSerialNumber);
certInfo.sSerialNumber = szSerialNumber;
/* Set Serial Number of Certificate*/
CertInfo.SerialNumber.cbData = 8;
CertInfo.SerialNumber.pbData = SerialNumber;
/* Set Signature Algorithm of Certificate*/
CRYPT_ALGORITHM_IDENTIFIER SubjKeyInfo;
CRYPT_OBJID_BLOB Parameters;
memset(&Parameters, 0, sizeof(Parameters));
SubjKeyInfo.pszObjId= szOID_RSA_MD5RSA;
SubjKeyInfo.Parameters = Parameters;
CertInfo.SignatureAlgorithm = SubjKeyInfo;
// дата начала действия
ZeroMemory(&sysTD, sizeof(sysTD));
sysTD.wYear= certInfo.dNotBefor.GetYear();
sysTD.wMonth= certInfo.dNotBefor.GetMonth();
sysTD.wDay= certInfo.dNotBefor.GetDay();
SystemTimeToFileTime(&sysTD, &udcTimeBefore);
CertInfo.NotBefore= udcTimeBefore;
// дата окончания действия
sysTD.wYear= certInfo.dNotAfter.GetYear();
sysTD.wMonth= certInfo.dNotAfter.GetMonth();
sysTD.wDay= certInfo.dNotAfter.GetDay();
SystemTimeToFileTime(&sysTD, &udcTimeAfter);
CertInfo.NotAfter= udcTimeAfter;
/* Get Public Key Info size*/
dwKeyType= AT_KEYEXCHANGE;
bResult = CryptExportPublicKeyInfo(hProv, dwKeyType,
ENCODING_TYPE, NULL, &dwSize);
if (!bResult)
{
printf("CryptExportPublicKeyInfo failed with %x\n", GetLastError());
return false;
}
/* Allocate memory for Public Key Info*/
PublicKeyInfo = (PCERT_PUBLIC_KEY_INFO)HeapAlloc(hHeap, 0, dwSize);
if (!PublicKeyInfo)
{
printf("Unable to allocate memory for public key info\n");
return false;
}
/* Get Public Key Info*/
bResult = CryptExportPublicKeyInfo(hProv, dwKeyType,
ENCODING_TYPE,
PublicKeyInfo, &dwSize);
if (!bResult)
{
printf("CryptExportPublicKeyInfo failed with %x\n", GetLastError());
return false;
}
/* Set Public Key info of Certificate*/
CertInfo.SubjectPublicKeyInfo = *PublicKeyInfo;
/* Create Hash*/
bResult = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
if (!bResult)
{
printf("CryptCreateHash failed with %x\n", GetLastError());
return false;
}
/* Hash Public Key Info*/
bResult = CryptHashData(hHash, (LPBYTE)PublicKeyInfo, dwSize, 0);
if (!bResult)
{
printf("CryptHashData failed with %x\n", GetLastError());
return false;
}
/* Get Size of Hash*/
bResult = CryptGetHashParam(hHash, HP_HASHVAL, NULL, &dwSize, 0);
if (!bResult)
{
printf("CryptGetHashParam failed with %x\n", GetLastError());
return false;
}
/* Allocate Memory for Key Identifier (hash of Public Key info)*/
pbKeyIdentifier = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!pbKeyIdentifier)
{
printf("Unable to allocate memory for Hashed Public key Info\n");
return false;
}
/* Get Hash of Public Key Info*/
bResult = CryptGetHashParam(hHash, HP_HASHVAL, pbKeyIdentifier, &dwSize, 0);
if (!bResult)
{
printf("CryptGetHashParam failed with %x\n", GetLastError());
return false;
}
/* We will use this to set the Key Identifier extension*/
CertKeyIdentifier.cbData = dwSize;
CertKeyIdentifier.pbData = pbKeyIdentifier;
/* Set Issuer of Certificate*/
if (bSelfSigned)
{
CertInfo.Subject = IssuerName;
CertInfo.Issuer = IssuerName;
}
else
{
pIssuerCert= CertCreateCertificateContext(ENCODING_TYPE, certInfo.pbRootCertBlob, certInfo.nRootCertBlobSize);
CertInfo.Subject = IssuerName;
CertInfo.Issuer = pIssuerCert->pCertInfo->Subject;
}
/* Get Subject Key Identifier Extension size*/
bResult = CryptEncodeObject(ENCODING,
szOID_SUBJECT_KEY_IDENTIFIER,
(LPVOID)&CertKeyIdentifier,
NULL, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Allocate Memory for Subject Key Identifier Blob*/
SubjectKeyIdentifier = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!SubjectKeyIdentifier)
{
printf("Unable to allocate memory for Subject Key Identifier\n");
return false;
}
/* Get Subject Key Identifier Extension*/
bResult = CryptEncodeObject(ENCODING,
szOID_SUBJECT_KEY_IDENTIFIER,
(LPVOID)&CertKeyIdentifier,
SubjectKeyIdentifier, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Set Subject Key Identifier*/
CertExtension[CertInfo.cExtension].pszObjId = szOID_SUBJECT_KEY_IDENTIFIER;
CertExtension[CertInfo.cExtension].fCritical = FALSE;
CertExtension[CertInfo.cExtension].Value.cbData = dwSize;
CertExtension[CertInfo.cExtension].Value.pbData = SubjectKeyIdentifier;
/* Increase extension count*/
CertInfo.cExtension++;
/* Set Key Usage according to Public Key Type*/
ZeroMemory(&KeyUsage, sizeof(KeyUsage));
KeyUsage.cbData = 1;
KeyUsage.pbData = &ByteData;
if (dwKeyType == AT_SIGNATURE)
{
ByteData = CERT_DIGITAL_SIGNATURE_KEY_USAGE|
CERT_NON_REPUDIATION_KEY_USAGE|
CERT_KEY_CERT_SIGN_KEY_USAGE |
CERT_CRL_SIGN_KEY_USAGE;
}
if (dwKeyType == AT_KEYEXCHANGE)
{
ByteData = CERT_DIGITAL_SIGNATURE_KEY_USAGE |
CERT_NON_REPUDIATION_KEY_USAGE;
}
/* Get Key Usage blob size*/
bResult = CryptEncodeObject(ENCODING,
X509_KEY_USAGE,
(LPVOID)&KeyUsage,
NULL, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Allocate Memory for Key Usage Blob*/
pbKeyUsage = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!pbKeyUsage)
{
printf("Unable to allocate memory for Subject Key Identifier\n");
return false;
}
/* Get Key Usage Extension blob*/
bResult = CryptEncodeObject(ENCODING,
X509_KEY_USAGE,
(LPVOID)&KeyUsage,
pbKeyUsage, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Set Key Usage extension*/
CertExtension[CertInfo.cExtension].pszObjId = szOID_KEY_USAGE;
CertExtension[CertInfo.cExtension].fCritical = FALSE;
CertExtension[CertInfo.cExtension].Value.cbData = dwSize;
CertExtension[CertInfo.cExtension].Value.pbData = pbKeyUsage;
/* Increase extension count*/
CertInfo.cExtension++;
// записываем роли пользователя
if(!certInfo.sUserRoles.IsEmpty())
{
certInfo.sUserRoles.Replace(";", "#");
char *strRoles= new char [certInfo.sUserRoles.GetLength()+1];
strcpy(strRoles, certInfo.sUserRoles);
CRYPT_DATA_BLOB roles;
roles.pbData= (PBYTE)strRoles;
roles.cbData= certInfo.sUserRoles.GetLength()+1;
CryptEncodeObject(ENCODING_TYPE, szOID_SUBJECT_KEY_IDENTIFIER, &roles,
NULL, &cbExtEncodedRole);
pbExtEncodedRole= new BYTE [cbExtEncodedRole];
CryptEncodeObject(ENCODING_TYPE, szOID_SUBJECT_KEY_IDENTIFIER, &roles,
pbExtEncodedRole, &cbExtEncodedRole);
//запись ролей
CertExtension[CertInfo.cExtension].pszObjId= szOID_USER_ROLE_SET;
CertExtension[CertInfo.cExtension].fCritical= FALSE;
CertExtension[CertInfo.cExtension].Value.cbData = cbExtEncodedRole;
CertExtension[CertInfo.cExtension].Value.pbData = pbExtEncodedRole;
CertInfo.cExtension++;
// память
delete [] strRoles;
delete [] pbExtEncodedRole;
}
if (CertEnhKeyUsage.cUsageIdentifier != 0)
{
/* Get Enhanced Key Usage size*/
bResult = CryptEncodeObject(ENCODING,
X509_ENHANCED_KEY_USAGE,
(LPVOID)&CertEnhKeyUsage,
NULL, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Allocate Memory for Enhanced Key usage Blob*/
pbEnhKeyUsage = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!pbEnhKeyUsage)
{
printf("Unable to allocate memory for Subject Key Identifier\n");
return false;
}
/* Get Enhanced Key Usage Extension blob*/
bResult = CryptEncodeObject(ENCODING,
X509_ENHANCED_KEY_USAGE,
(LPVOID)&CertEnhKeyUsage,
pbEnhKeyUsage, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Set Enhanced Key Usage extension*/
CertExtension[CertInfo.cExtension].pszObjId = szOID_ENHANCED_KEY_USAGE;
CertExtension[CertInfo.cExtension].fCritical = FALSE;
CertExtension[CertInfo.cExtension].Value.cbData = dwSize;
CertExtension[CertInfo.cExtension].Value.pbData = pbEnhKeyUsage;
/* Increase extension count*/
CertInfo.cExtension++;
}
/* Zero Basic Constraints structure*/
ZeroMemory(&BasicConstraints, sizeof(BasicConstraints));
/* Self-signed is always a CA*/
if (bSelfSigned)
{
BasicConstraints.fCA = TRUE;
BasicConstraints.fPathLenConstraint = TRUE;
BasicConstraints.dwPathLenConstraint = 1;
}
else
{
BasicConstraints.fCA = false;
}
/* Get Basic Constraints blob size*/
bResult = CryptEncodeObject(ENCODING,
X509_BASIC_CONSTRAINTS2,
(LPVOID)&BasicConstraints,
NULL, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Allocate Memory for Basic Constraints Blob*/
pbBasicConstraints = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!pbBasicConstraints)
{
printf("Unable to allocate memory for Subject Key Identifier\n");
return false;
}
/* Get Basic Constraints Extension blob*/
bResult = CryptEncodeObject(ENCODING,
X509_BASIC_CONSTRAINTS2,
(LPVOID)&BasicConstraints,
pbBasicConstraints, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Set Basic Constraints extension*/
CertExtension[CertInfo.cExtension].pszObjId = szOID_BASIC_CONSTRAINTS2;
CertExtension[CertInfo.cExtension].fCritical = FALSE;
CertExtension[CertInfo.cExtension].Value.cbData = dwSize;
CertExtension[CertInfo.cExtension].Value.pbData = pbBasicConstraints;
/* Increase extension count*/
CertInfo.cExtension++;
if (bSelfSigned)
{
AuthorityKeyId.KeyId = CertKeyIdentifier;
AuthorityKeyId.CertIssuer = CertInfo.Issuer;
AuthorityKeyId.CertSerialNumber = CertInfo.SerialNumber;
bAddAuthorityExtension = TRUE;
}
else
{
if (pIssuerCert)
{
AuthorityKeyId.KeyId.cbData = 0;
AuthorityKeyId.KeyId.pbData = NULL;
AuthorityKeyId.CertIssuer = pIssuerCert->pCertInfo->Issuer;
AuthorityKeyId.CertSerialNumber = pIssuerCert->pCertInfo->SerialNumber;
bAddAuthorityExtension = TRUE;
}
}
if (bAddAuthorityExtension)
{
/* Get Authority Key Id blob size*/
bResult = CryptEncodeObject(ENCODING,
X509_AUTHORITY_KEY_ID,
(LPVOID)&AuthorityKeyId,
NULL, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Allocate Authority Key Id Blob*/
pbAuthorityKeyId = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!pbAuthorityKeyId)
{
printf("Unable to allocate memory for Subject Key Identifier\n");
return false;
}
/* Get Authority Key Id blob*/
bResult = CryptEncodeObject(ENCODING,
X509_AUTHORITY_KEY_ID,
(LPVOID)&AuthorityKeyId,
pbAuthorityKeyId, &dwSize);
if (!bResult)
{
printf("CryptEncodeObject failed with %x\n", GetLastError());
return false;
}
/* Set Authority Key Id extension*/
CertExtension[CertInfo.cExtension].pszObjId = szOID_AUTHORITY_KEY_IDENTIFIER;
CertExtension[CertInfo.cExtension].fCritical = FALSE;
CertExtension[CertInfo.cExtension].Value.cbData = dwSize;
CertExtension[CertInfo.cExtension].Value.pbData = pbAuthorityKeyId;
/* Increase extension count*/
CertInfo.cExtension++;
}
CertInfo.rgExtension = CertExtension;
if (bSelfSigned)
{
/* Get Encoded Certificate Size*/
bResult = CryptSignAndEncodeCertificate(hProv, AT_KEYEXCHANGE,
/*X509_ASN_ENCODING*/(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), X509_CERT_TO_BE_SIGNED,
(LPVOID)&CertInfo,
&(CertInfo.SignatureAlgorithm),
NULL, NULL, &dwSize);
if (!bResult)
{
printf("CryptSignAndEncodeCertificate failed with %x\n", GetLastError());
ShowError(GetLastError());
return false;
}
/* Allocate memory for encoded certificate*/
bpEncodedCert = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!bpEncodedCert)
{
printf("Unable to allocate memory for encoded certficate\n");
return false;
}
/* Sign and Encode certificate*/
bResult = CryptSignAndEncodeCertificate(hProv, AT_KEYEXCHANGE,
/*X509_ASN_ENCODING*/(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), X509_CERT_TO_BE_SIGNED,
(LPVOID)&CertInfo,
&(CertInfo.SignatureAlgorithm),
NULL, bpEncodedCert, &dwSize);
if (!bResult)
{
printf("CryptSignAndEncodeCertificate failed with %x\n", GetLastError());
return false;
}
}
else
{
/* Get Encoded Certificate Size*/
bResult = CryptSignAndEncodeCertificate(hCryptProvCA, AT_SIGNATURE,
(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), X509_CERT_TO_BE_SIGNED,
(LPVOID)&CertInfo,
&(CertInfo.SignatureAlgorithm),
//&(pIssuerCert->pCertInfo->SignatureAlgorithm),
NULL, NULL, &dwSize);
if (!bResult)
{
ShowError(GetLastError());
printf("CryptSignAndEncodeCertificate failed with %x\n", GetLastError());
return false;
}
/* Allocate memory for encoded certificate*/
bpEncodedCert = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!bpEncodedCert)
{
printf("Unable to allocate memory for encoded certficate\n");
return false;
}
/* Sign and Encode certificate*/
bResult = CryptSignAndEncodeCertificate(hCryptProvCA, AT_SIGNATURE,
(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), X509_CERT_TO_BE_SIGNED,
(LPVOID)&CertInfo,
&(CertInfo.SignatureAlgorithm),
//&(pIssuerCert->pCertInfo->SignatureAlgorithm),
NULL, bpEncodedCert, &dwSize);
if (!bResult)
{
printf("CryptSignAndEncodeCertificate failed with %x\n", GetLastError());
return false;
}
}
// Открытый ключ способ №2
CString sOpenKey;
int iOpenKeyLen= 2*CertInfo.SubjectPublicKeyInfo.PublicKey.cbData + 1;
LPSTR szOpenKey= certInfo.sOpenKey.GetBuffer(iOpenKeyLen);
ByteToStr(CertInfo.SubjectPublicKeyInfo.PublicKey.cbData, CertInfo.SubjectPublicKeyInfo.PublicKey.pbData, szOpenKey);
// создаем сертификат
num = dwSize;
certInfo.sFilePath = getenv("TEMP");
certInfo.sFilePath += "\\" + certInfo.sSerialNumber + ".cer";
WriteToFile(certInfo.sFilePath, bpEncodedCert, num);
// помещаем его в хранилище
if(bSelfSigned)
{
WCHAR szwStore[50] = L"Trust";
WCHAR szwProvider[260];
WCHAR szwContainer[160];
CRYPT_KEY_PROV_INFO CryptKeyProvInfo;
/* Convert Store string to unicode*/
int i = MultiByteToWideChar(0, 0, "Мое хранилище", -1, szwStore, 50);
if (i == 0) return false;
i = MultiByteToWideChar(0, 0, szProvider, -1, szwProvider, 260);
if (i == 0) return false;
/* Open Certificate store*/
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER, (LPVOID)L"Root");
if (!hStore) return false;
/* Place Certificate in store*/
bResult = CertAddEncodedCertificateToStore(hStore, X509_ASN_ENCODING, bpEncodedCert, dwSize, /*CERT_STORE_ADD_REPLACE_EXISTING*/CERT_STORE_ADD_REPLACE_EXISTING, &pCertContext);
if (!bResult) return false;
/* Convert container to unicode*/
i = MultiByteToWideChar(0, 0, szContainer, -1, szwContainer, 160);
if (i == 0) return false;
/* Initialize CRYPT_KEY_PROV_INFO structure*/
ZeroMemory(&CryptKeyProvInfo, sizeof(CryptKeyProvInfo));
CryptKeyProvInfo.pwszContainerName = szwContainer;
CryptKeyProvInfo.pwszProvName = szwProvider;
CryptKeyProvInfo.dwProvType = dwProviderType;
CryptKeyProvInfo.dwKeySpec = dwKeyType;
CryptKeyProvInfo.dwFlags = dwAcquireFlags;
/* Set Certificate's Key Provider info*/
bResult = CertSetCertificateContextProperty(pCertContext, CERT_KEY_PROV_INFO_PROP_ID, 0, (LPVOID)&CryptKeyProvInfo);
PCCERT_CONTEXT pContext= CertCreateCertificateContext(ENCODING_TYPE, bpEncodedCert, num);
CertAddCertificateContextToStore(hStore, pContext, CERT_STORE_ADD_ALWAYS, 0);
}
// создаем файл с секретным ключом
MakeSecretKeyFile(&hProv, sFile, sPassword, hPubKey, dwSize, bpEncodedCert, certInfo.sContainer);
// проверяем сертификат на подпись
if(!bSelfSigned)
{
DWORD dwSignSize;
BYTE *pbSign = 0;
BOOL bRes = CryptSignCertificate(hCryptProvCA, AT_KEYEXCHANGE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, bpEncodedCert, dwSize, &(CertInfo.SignatureAlgorithm), 0, 0, &dwSignSize);
pbSign = new BYTE[dwSignSize];
bRes = CryptSignCertificate(hCryptProvCA, AT_KEYEXCHANGE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, bpEncodedCert, dwSize, &(CertInfo.SignatureAlgorithm), 0, pbSign, &dwSignSize);
if(!bRes) ShowError(GetLastError());
if(!CryptVerifyCertificateSignature(hCryptProvCA, X509_ASN_ENCODING, bpEncodedCert, dwSize, PublicKeyInfo))
ShowError(GetLastError());
if(!CryptVerifyCertificateSignature(hProv, X509_ASN_ENCODING, bpEncodedCert, dwSize, PublicKeyInfo))
ShowError(GetLastError());
}
else
{
if(!CryptVerifyCertificateSignature(hProv, X509_ASN_ENCODING, bpEncodedCert, dwSize, PublicKeyInfo))
ShowError(GetLastError());
}
// Clean up
if (PublicKeyInfo) HeapFree(hHeap, 0, PublicKeyInfo);
if (pbKeyIdentifier) HeapFree(hHeap, 0, pbKeyIdentifier);
if (SubjectKeyIdentifier) HeapFree(hHeap, 0, SubjectKeyIdentifier);
if (pbKeyUsage) HeapFree(hHeap, 0, pbKeyUsage);
if (pbEnhKeyUsage) HeapFree(hHeap, 0, pbEnhKeyUsage);
if (pbBasicConstraints) HeapFree(hHeap, 0, pbBasicConstraints);
if (KeyId) HeapFree(hHeap, 0, KeyId);
if (pbAuthorityKeyId) HeapFree(hHeap, 0, pbAuthorityKeyId);
if (bpEncodedCert) HeapFree(hHeap, 0, bpEncodedCert);
if (pbExportedKey) HeapFree(hHeap, 0, pbExportedKey);
if (hCertFile) CloseHandle(hCertFile);
if (hKeyFile) CloseHandle(hKeyFile);
if (hPubKey) CryptDestroyKey(hPubKey);
if (hSessionKey) CryptDestroyKey(hSessionKey);
if (hHash) CryptDestroyHash(hHash);
if (hProv) CryptReleaseContext(hProv, 0);
if (hIssuerProv) CryptReleaseContext(hIssuerProv, 0);
if (pIssuerCert) CertFreeCertificateContext(pIssuerCert);
if (pCertContext) CertFreeCertificateContext(pCertContext);
if (hStore) CertCloseStore(hStore, 0);
if (pbData) delete [] pbData;
if (szSerialNumber) delete [] szSerialNumber;
return bReturn;
}
|