我有一项开发CNG的任务。我得到了一个工作的CNG源代码,它支持GOST等算法。我需要让它生成私钥(pkcs8格式)并支持其他结构中的x509证书。例如:
这是由CNG在PKCS8中生成的私钥:
3042020100301906092A865C030F01010201300C060A2A865C030F010102010104220220583E4721B1854891532AC05E7033B77D2D357A418A99D473CF05125EA6BDE2C8
ASN1:
SEQUENCE(3 elem)
INTEGER 0
SEQUENCE(2 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1
SEQUENCE(1 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1.1
OCTET STRING(1 elem)
INTEGER(255 bit) 3991356612570766941491045091107680786406690561132958956606466907746255…
我需要在此结构中生成私钥(pkcs8):
30819A020100301706092A865C030F01010201060A2A865C030F0101020101047C307A020101042024342757366A76776A2E13580929AD7E3D26B2C11656F30CD7CAF32A354B78D5A00C060A2A865C030F0101020101A145034300044058713A68F3EF7AD72BE6DFCCEBC6576A37B97E2A753C5A34FAA0C3BC818AE461E6F0E2C397BCBFF1314B19A25AF30DCD2653F90B1D73908EB5568D0BAFA87DD1
ASN1:
SEQUENCE(3 elem)
INTEGER 0
SEQUENCE(2 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1.1
OCTET STRING(1 elem)
SEQUENCE(4 elem)
INTEGER 1
OCTET STRING(32 byte) 24342757366A76776A2E13580929AD7E3D26B2C11656F30CD7CAF32A354B78D5
[0](1 elem)
OBJECT IDENTIFIER 1.2.860.3.15.1.1.2.1.1
[1](1 elem)
BIT STRING(1 elem)
OCTET STRING(64 byte) 58713A68F3EF7AD72BE6DFCCEBC6576A37B97E2A753C5A34FAA0C3BC818AE461E6F0E2…
是否有人可以帮助我,我应该寻求改变任何想法或解决方案。
以下函数分配内存并生成私钥的ASN缓冲区,算法参数和给定CNG的算法名称 斑点。需要这些缓冲区来填充Crypt_private_key_info结构。 我想我需要改变这段代码:
SxKS_AllocAndEncodePrivateKey(
__in PBYTE pbKeyBlobCNG,
__in DWORD cbKeyBlobCNG,
__out PBYTE *ppbKeyBufASN,
__out DWORD *pcbKeyBufASN,
__out PBYTE *ppbAlgParamASN,
__out DWORD *pcbAlgParamASN,
__out LPSTR *pszAlgOID)
{
PBYTE pbKeyBufASN = NULL;
DWORD cbKeyBufASN = 0;
PBYTE pbAlgParamASN = NULL;
DWORD cbAlgParamASN = 0;
LPSTR szAlgOID = NULL;
PSTYX_SYMMKEY_BLOB pSymmBlob = NULL;
PSTYX_ASYMMKEY_BLOB pAsymmBlob = NULL;
PSTYX_KEYBLOB_HEADER pHdrBlob = NULL;
SECURITY_STATUS Status = ERROR_SUCCESS;
ULONG dwPubParamId = 0;
ULONG dwMDParamId = 0;
ULONG dwEncParamId = 0;
ULONG cbParam1 = 0;
ULONG cbParam2 = 0;
PBYTE pPrivKeyData;
DWORD fLeadingZero = 0;
// Проверяем входные данные
if ((NULL == pbKeyBlobCNG) ||
(0 == cbKeyBlobCNG) ||
(NULL == ppbKeyBufASN) ||
(NULL == pcbKeyBufASN) ||
(NULL == ppbAlgParamASN) ||
(NULL == pcbAlgParamASN) ||
(NULL == pszAlgOID))
{
Status = NTE_BAD_DATA;
goto Cleanup;
}
pHdrBlob = (PSTYX_KEYBLOB_HEADER)pbKeyBlobCNG;
// Проверяем корректность блоба
if (0 == pHdrBlob->cbKey)
{
Status = NTE_BAD_DATA;
goto Cleanup;
}
pAsymmBlob = (PSTYX_ASYMMKEY_BLOB)pbKeyBlobCNG;
// Проверяем корректность блоба
// Длина ключа
if ((sizeof(STYX_ASYMMKEY_BLOB) + 3 * pAsymmBlob->cbKey) < cbKeyBlobCNG)
{
Status = NTE_BAD_DATA;
goto Cleanup;
}
dwPubParamId = pAsymmBlob->dwPubParamId;
// При необходимости задаем параметры алгоритма по умолчанию.
if (0 == dwPubParamId)
dwPubParamId = 2;
dwMDParamId = pAsymmBlob->dwMDParamId;
// При необходимости задаем блок подстановок хэш по умолчанию.
if (0 == dwMDParamId)
dwMDParamId = 10;
dwEncParamId = pAsymmBlob->dwEncParamId;
// При необходимости задаем блок подстановок по умолчанию.
if (0 == dwEncParamId)
dwEncParamId = 2;
// Устанавливаем указатель значения закрытого ключа
pPrivKeyData = pbKeyBlobCNG + sizeof(STYX_ASYMMKEY_BLOB) + 2 * pAsymmBlob->cbKey;
// Считаем размер для ASN буфера закрытого ключа
// TRIPLET INTEGER (1) + LENGTH (1) + KEYDATA (32) = 34
cbKeyBufASN = 2 + pAsymmBlob->cbKey;
// Устанавливаем флаг fLeadingZero для триплета INTEGER
if (0x80 == (0x80 & pPrivKeyData[0]))
{
fLeadingZero = 1;
cbKeyBufASN++;
}
// Выделяем память для ASN буфера закрытого ключа
pbKeyBufASN = (PBYTE)STYXMALLOC(cbKeyBufASN);
if (NULL == pbKeyBufASN)
{
Status = NTE_NO_MEMORY;
goto Cleanup;
}
// Заполняем ASN буфер закрытого ключа
pbKeyBufASN[0] = 0x02; // ASN.1 TRIPLET TYPE INTEGER
pbKeyBufASN[1] = (BYTE) pAsymmBlob->cbKey; // ASN.1 TRIPLET LENGTH 32 octets
if (1 == fLeadingZero)
{
pbKeyBufASN[1]++;
pbKeyBufASN[2] = 0;
memcpy(pbKeyBufASN + 3, pPrivKeyData, pAsymmBlob->cbKey);
}
else
{
memcpy(pbKeyBufASN + 2, pPrivKeyData, pAsymmBlob->cbKey);
}
// Считаем размер для ASN буфера параметров алгоритма
// TRIPLET SEQ (1) + SEQLEN(1) +
// OBJ(1) + OBJLEN(1) + PubParamOIDdata +
// OBJ(1) + OBJLEN(1) + MDParamOIDdata
SxH_GetOIDoctets_fromGS01PubParamID(dwPubParamId, NULL, &cbParam1);
SxH_GetOIDoctets_fromSBoxID(dwMDParamId, NULL, &cbParam2);
cbAlgParamASN = 6 + (BYTE)(cbParam1 + cbParam2);
// Выделяем память для ASN буфера параметров алгоритма
pbAlgParamASN = (PBYTE)STYXMALLOC(cbAlgParamASN);
if (NULL == pbAlgParamASN)
{
Status = NTE_NO_MEMORY;
goto Cleanup;
}
// Заполняем ASN буфер параметров алгоритма
pbAlgParamASN[0] = 0x30; // ASN.1 TRIPLET SEQ
pbAlgParamASN[1] = 4 + (BYTE)(cbParam1 + cbParam2); // ASN.1 TRIPLET SEQ LEN
pbAlgParamASN[2] = 0x06; // ASN.1 TRIPLET OBJ
pbAlgParamASN[3] = (BYTE)cbParam1; // ASN.1 TRIPLET OBJ LEN
SxH_GetOIDoctets_fromGS01PubParamID(dwPubParamId, pbAlgParamASN + 4, &cbParam1);
pbAlgParamASN[4 + cbParam1] = 0x06; // ASN.1 TRIPLET OBJ
pbAlgParamASN[5 + cbParam1] = (BYTE)cbParam2; // ASN.1 TRIPLET OBJ LEN
SxH_GetOIDoctets_fromSBoxID(dwEncParamId, pbAlgParamASN + 6 + cbParam1, &cbParam2);
// Заполняе указатель OID'а алгоритма
szAlgOID = szOID_OS_A2;
*ppbKeyBufASN = pbKeyBufASN;
*pcbKeyBufASN = cbKeyBufASN;
*ppbAlgParamASN = pbAlgParamASN;
*pcbAlgParamASN = cbAlgParamASN;
*pszAlgOID = szAlgOID;
// Сбрасываем указатели чтобы не освобождать память буферов при выходе
pbKeyBufASN = NULL;
pbAlgParamASN = NULL;
Cleanup:
if (NULL != pbKeyBufASN) STYXFREE(pbKeyBufASN);
if (NULL != pbAlgParamASN) STYXFREE(pbAlgParamASN);
return Status;
}