(2015-11-02 18:28:40 отредактировано Oleg Taraskin)

Re: Импорт ключа

Дело в том, что OID парамсета 1.2.643.2.2.35.1 говорит о том, что пару можно использовать только для подписи
а 1.2.643.2.2.36.0 как для подписи, так и для DH.
см. http://cpdn.cryptopro.ru/content/csp36/ … _OIDS.html
Это несмотря на то, что по сути кривые с OID 1.2.643.2.2.35.1 и 1.2.643.2.2.36.0  - одинаковые.
Поэтому CryptoPro CSP и "ругается".  Если вы хотите использовать пару из PKCS#11 для DH то сгенерируйте ее с атрибутом
CKA_GOSTR3410_PARAMS равным 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x24, 0x00

(2015-11-06 18:37:28 отредактировано SvetovidovDM)

Re: Импорт ключа

Oleg Taraskin пишет:

Дело в том, что OID парамсета 1.2.643.2.2.35.1 говорит о том, что пару можно использовать только для подписи
а 1.2.643.2.2.36.0 как для подписи, так и для DH.
см. http://cpdn.cryptopro.ru/content/csp36/ … _OIDS.html
Это несмотря на то, что по сути кривые с OID 1.2.643.2.2.35.1 и 1.2.643.2.2.36.0  - одинаковые.
Поэтому CryptoPro CSP и "ругается".  Если вы хотите использовать пару из PKCS#11 для DH то сгенерируйте ее с атрибутом
CKA_GOSTR3410_PARAMS равным 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x24, 0x00

Спасибо, правда я пошел несколько другим путем, потому как в реальной жизни ключи будут попадаться самые разные. Поэтому вместо того чтобы использовать ключ отправителя генерирую эфемерный ключ и использую его закрытую часть для шифрования сессионного ключа, а открытую часть собираю в блоб и передаю вместе с данными.

Re: Импорт ключа

SvetovidovDM пишет:
Oleg Taraskin пишет:

Дело в том, что OID парамсета 1.2.643.2.2.35.1 говорит о том, что пару можно использовать только для подписи
а 1.2.643.2.2.36.0 как для подписи, так и для DH.
см. http://cpdn.cryptopro.ru/content/csp36/ … _OIDS.html
Это несмотря на то, что по сути кривые с OID 1.2.643.2.2.35.1 и 1.2.643.2.2.36.0  - одинаковые.
Поэтому CryptoPro CSP и "ругается".  Если вы хотите использовать пару из PKCS#11 для DH то сгенерируйте ее с атрибутом
CKA_GOSTR3410_PARAMS равным 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x24, 0x00

Спасибо, правда я пошел несколько другим путем, потому как в реальной жизни ключи будут попадаться самые разные. Поэтому вместо того чтобы использовать ключ отправителя генерирую эфемерный ключ и использую его закрытую часть для шифрования сессионного ключа, а открытую часть собираю в блоб и передаю вместе с данными.
Теперь экспорт и импорт ключей отрабатывает,но при расшифровке самого сообщения через CryptDecrypt получаю абсолютно не те данные которые должен был, хотя длина считается корректно, и сам метод не возвращает ошибки.

А как тогда используется вторая неэфемеральная пара ? Т.е. я правильно понял, что вы решили сделать одностороннюю аутентификацию ?

Re: Импорт ключа

Oleg Taraskin пишет:
SvetovidovDM пишет:
Oleg Taraskin пишет:

Дело в том, что OID парамсета 1.2.643.2.2.35.1 говорит о том, что пару можно использовать только для подписи
а 1.2.643.2.2.36.0 как для подписи, так и для DH.
см. http://cpdn.cryptopro.ru/content/csp36/ … _OIDS.html
Это несмотря на то, что по сути кривые с OID 1.2.643.2.2.35.1 и 1.2.643.2.2.36.0  - одинаковые.
Поэтому CryptoPro CSP и "ругается".  Если вы хотите использовать пару из PKCS#11 для DH то сгенерируйте ее с атрибутом
CKA_GOSTR3410_PARAMS равным 0x06, 0x07, 0x2A, 0x85, 0x03, 0x02, 0x02, 0x24, 0x00

Спасибо, правда я пошел несколько другим путем, потому как в реальной жизни ключи будут попадаться самые разные. Поэтому вместо того чтобы использовать ключ отправителя генерирую эфемерный ключ и использую его закрытую часть для шифрования сессионного ключа, а открытую часть собираю в блоб и передаю вместе с данными.
Теперь экспорт и импорт ключей отрабатывает,но при расшифровке самого сообщения через CryptDecrypt получаю абсолютно не те данные которые должен был, хотя длина считается корректно, и сам метод не возвращает ошибки.

А как тогда используется вторая неэфемеральная пара ? Т.е. я правильно понял, что вы решили сделать одностороннюю аутентификацию ?

Расшифровку через CryptDecrypt починил, оказалась проблема в несогласованном механизме шифрования.

Вторая пара не используется.
Механизм шифрования следующий:
1. Получаем параметры кривых открытого ключа получателя.
2. Генерируем эфемерную ключевую пару
3. Вырабатываем ключ согласования из открытого ключа отправителя и закрытого эфемерной пары
4. Генерируем сессионный ключ и шифруем его на ключе согласования
5. Собираем блоб открытого ключа эфемерной пары
6. шифруем данные сессионным ключом.


Собираем все это в структуру и передаем на сервер.
При расшифровке делаем так:
1. Берем закрытый ключ получателя
2. Берем значение открытого ключа из блоба
3. Получаем из этих ключей ключ согласования
4. Расшифровываем этим ключом сессионный ключ
5. Расшифровываем данные сессионным ключом.

Теперь работает - шифрование на PKCS#11 и CryptoAPI
Расшифровка - на CryptoAPI

На PKCS#11 расшифровка не проходит, при выработке общего ключа получаю ошибку 0x00000071, хотя та же функция работает и при выработке общего ключа для шифрования, и проходит успешно.

Re: Импорт ключа

Вероятнее всего проблема в получении данных открытого ключа из блоба в пригодном для PKCS#11 виде.
Когда я получаю открытый ключ сертификата, я просто вычитываю из ASN.1 структуры сертификата открытый ключ. Он получается равным 64 байта.
А вот когда я получаю значение CKA_VALUE из объекта открытого ключа, я получаю всего 44 байта.
Как я понимаю, первые 20 байт это ASN.1 структура содержащая в себе параметры кривых.

В общем суть такова. Если я передаю в функцию C_DeriveKey 44 байта (сам ключ) получаю ошибку 0x00000071
Если передаю 64 байта (Параметры и ключ) то получаю ошибку 0x00000030

Re: Импорт ключа

Знаете, это очень странно, что вы получаете 44 байта. В CKA_VALUE открытого ключа
ГОСТ Р 34.10-2001 должна быть точка эллиптической кривой с длиной 64 байта.
Можете прислать код, который это делает ?

(2015-11-10 16:31:59 отредактировано SvetovidovDM)

Re: Импорт ключа

Oleg Taraskin пишет:

Знаете, это очень странно, что вы получаете 44 байта. В CKA_VALUE открытого ключа
ГОСТ Р 34.10-2001 должна быть точка эллиптической кривой с длиной 64 байта.
Можете прислать код, который это делает ?

Пожалуйста.
Код который получает значение открытого ключа и формирует из него блоб.

CK_ATTRIBUTE    stAttrValue[] = { { CKA_VALUE, NULL, 0 } };
        if( lRetCode == CKR_OK )
            lRetCode = pstFL->C_GetAttributeValue( m_hSession, hPublicKey, &stAttrValue[0], sizeof( stAttrValue ) / sizeof( stAttrValue[0] ));
        if( lRetCode == CKR_OK )
        {
            stAttrValue[0].pValue = ( stAttrValue[0].ulValueLen != 0 ? new BYTE[stAttrValue[0].ulValueLen] : NULL );
            if( stAttrValue[0].pValue == NULL )
                lRetCode = CKR_HOST_MEMORY;
            else
            {
                lRetCode = pstFL->C_GetAttributeValue( m_hSession, hPublicKey, &stAttrValue[0], sizeof( stAttrValue ) / sizeof( stAttrValue[0] ));
                if( lRetCode == CKR_OK )
                {
                    UINT    nSizeKeyParams = 0;
                    BYTE*    pbtKeyParams = NULL;
                    // Формируем поле параметров алгоритма электронной подписи
                    CSCLTLVField*    pfieldParameters = CProvider::asn1NewFieldParameters( m_nAlgorithm, nAlgParams );
                    if( pfieldParameters != NULL )
                    {
                        nSizeKeyParams = pfieldParameters->MakeBuffer( NULL );
                        pbtKeyParams = new BYTE[nSizeKeyParams];
                        if( pbtKeyParams != NULL )
                            nSizeKeyParams = pfieldParameters->MakeBuffer( pbtKeyParams );
                        else
                            nSizeKeyParams = 0;

                        delete pfieldParameters;
                    }

                    dwBlobLen = sizeof( CRYPT_PUBLICKEYBLOB::CRYPT_PUBKEY_INFO_HEADER ) + nSizeKeyParams + stAttrValue[0].ulValueLen;
                    pbtEphemBlob = new BYTE[dwBlobLen];
                    if( pbtEphemBlob != NULL )
                    {
                        CRYPT_PUBLICKEYBLOB*    pstCPKB = ( CRYPT_PUBLICKEYBLOB* )pbtEphemBlob;
                        pstCPKB->stPublicKeyParam.BlobHeader.bType = 0x06/*PUBLICKEYBLOB*/;
                        pstCPKB->stPublicKeyParam.BlobHeader.bVersion = 0x20/*BLOB_VERSION*/;
                        pstCPKB->stPublicKeyParam.BlobHeader.reserved = 0;
                        pstCPKB->stPublicKeyParam.BlobHeader.aiKeyAlg = 0x00002E23/*CALG_GR3410EL*/;
                        pstCPKB->stPublicKeyParam.KeyParam.Magic = 0x3147414D/*GR3410_1_MAGIC*/;
                        pstCPKB->stPublicKeyParam.KeyParam.BitLen = (nKeySize+nSizeKeyParams) * 8;
                        memcpy( &pbtEphemBlob[sizeof( CRYPT_PUBLICKEYBLOB::CRYPT_PUBKEY_INFO_HEADER )], pbtKeyParams, nSizeKeyParams );
                        memcpy( &pbtEphemBlob[sizeof( CRYPT_PUBLICKEYBLOB::CRYPT_PUBKEY_INFO_HEADER ) + nSizeKeyParams], stAttrValue[0].pValue, stAttrValue[0].ulValueLen );
                    }
                    if(pbtKeyParams)
                        delete [] pbtKeyParams;
                }

                delete [] ( BYTE* )stAttrValue[0].pValue;
            }
        }

Код который получает из блоба открытый ключ

    BYTE* pbtKeyInfo=(BYTE*)&pbtPublicKeyBlob[sizeof( CRYPT_PUBLICKEYBLOB::CRYPT_PUBKEY_INFO_HEADER )];
    CK_ULONG ulKeylength=((CRYPT_PUBLICKEYBLOB*)pbtPublicKeyBlob)->stPublicKeyParam.KeyParam.BitLen/8;
    ASSERT(ulKeylength==64);
    nKeySize=ulKeylength;
    return pbtKeyInfo;

Код генерации ключа присылал раньше. Единственное отличие - параметры кривых выставляются такие же как и в открытом ключе.

Re: Импорт ключа

Скажите, а какая версия библиотеки PKCS#11 у вас ? Можете ее прислать ?

(2015-11-10 18:41:41 отредактировано SvetovidovDM)

Re: Импорт ключа

Oleg Taraskin пишет:

Скажите, а какая версия библиотеки PKCS#11 у вас ? Можете ее прислать ?

Та которая в комплекте с вашим SDK. 1.1.5.0

Прислать куда?
Если возможно, напишите мне на e-mail (svetovidov@itopcase.ru).

Re: Импорт ключа

Пришлите, пожалуйста на tog  с о б а к а   rutoken.ru

Re: Импорт ключа

У вас в итоге все получилось?