以特定的pkcs8格式生成私钥(自定义CNG)

时间:2018-06-14 10:40:25

标签: c cng

我有一项开发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;
}

0 个答案:

没有答案