Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline zhdamorev  
#1 Оставлено : 12 февраля 2018 г. 15:30:07(UTC)
zhdamorev

Статус: Новичок

Группы: Участники
Зарегистрирован: 06.02.2018(UTC)
Сообщений: 5
Мужчина
Российская Федерация
Откуда: Санкт-Петербург

Сказал «Спасибо»: 1 раз
Добрый день,
реализую шифрование xml сообщения по алгоритму ГОСТ 28147-89 для электронного обмена с ФСС на C#,
алгоритм реализован вручную отдельным классом наследуемым от SymmitricAlgorithm
для того чтобы встроить его в механизм стандартной реализации EncryptedXML
(подобное встраивание судя по примерам реализовано в КриптоПро.NET),
но
реализация SymmitricAlgorithm требует явной генерации сессионного ключа.

При попытке сгенерировать сессионный ключ при помощи CryptGenKey и после экспортировать его значение CryptExportKey
выдаёт ошибку -2146893814

Код:

public byte[] GetSessionKey(X509Certificate2 cert, int keyLength)
        {

            IntPtr phCryptProv = IntPtr.Zero;
            IntPtr phKey = IntPtr.Zero;
            int pdwKeySpec = 0;
            bool pfCallerKeyProv = false;
            byte[] sessionKeyResultArray = null;
            
            if (Api.CryptAcquireCertificatePrivateKey(cert.Handle, 0, IntPtr.Zero, ref phCryptProv, ref pdwKeySpec, ref pfCallerKeyProv))
            {
                try
                {
                    if(!Api.CryptGenKey(phCryptProv, Api.CALG_G28147, Api.CRYPT_EXPORTABLE, ref phKey))
                    {
                        int error = Marshal.GetLastWin32Error();
                        throw new Win32Exception("Crypt gen key error!");
                    }

                    int bufferSize = 0;

                    /*simpleblob 0x1, plaintextblob 0x8*/
                    if (!Api.CryptExportKey(phKey, IntPtr.Zero, /*Api.PLAINTEXTKEYBLOB*/0x8, 0, IntPtr.Zero, ref bufferSize))
                    {
                        int error = Marshal.GetLastWin32Error();
                        //ошибка -2146893814
                        throw new Win32Exception("Crypt export key error!");
                    }
                    

                    sessionKeyResultArray = new byte[bufferSize];

                    GCHandle gcHandle = GCHandle.Alloc((object)sessionKeyResultArray, GCHandleType.Pinned);
                    try
                    {
                         if (!Api.CryptExportKey(phKey, IntPtr.Zero, /*Api.PLAINTEXTKEYBLOB*/0x8, 0, gcHandle.AddrOfPinnedObject(), ref bufferSize))
                            throw new Win32Exception("Crypt export key error!");
                    }
                    finally
                    {
                        gcHandle.Free();
                    }
                }
                finally
                {
                    if (phKey != IntPtr.Zero)
                    {
                        if (!Api.CryptDestroyKey(phKey))
                            throw new Win32Exception("Crypt destroy key error!");
                    }
                    if (pfCallerKeyProv)
                    {
                        if (!Api.CryptReleaseContext(phCryptProv, 0))
                            throw new Win32Exception("Crypt release context error!");
                    }


                }
            }
            return sessionKeyResultArray;
        }


Таким образом видимо экспортировать ключ нельзя (почему?).

Кроме того сгенерированный сессионный ключ нам нужно потом зашифровать на сертификате (открытом ключе) получателя.

Тогда можно ли сгенерировать ключ как рандомный массив байтов (например через CryptGenRandom),
зашифровать им сообщение и зашифровать данный массив байтов как ключ сессии на сертификате получателя?


ПС.
Интересна возможность реализации именно в таком варианте,
примеры из руководства программиста изучал, но там представлен альтернативный вариант.
Offline Максим Коллегин  
#2 Оставлено : 13 февраля 2018 г. 8:03:10(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
Ключи КриптоПро CSP могут быть эспортированы только на других ключах и сгенерированы только внутри криптопровайдера.
Знания в базе знаний, поддержка в техподдержке
Offline zhdamorev  
#3 Оставлено : 13 февраля 2018 г. 12:28:36(UTC)
zhdamorev

Статус: Новичок

Группы: Участники
Зарегистрирован: 06.02.2018(UTC)
Сообщений: 5
Мужчина
Российская Федерация
Откуда: Санкт-Петербург

Сказал «Спасибо»: 1 раз
То есть извлечь значение сессионного ключа для использования его вне криптопровайдера нельзя,
так же как и сгенерировать рандомный ключ и потом импортировать его для того чтобы зашифровать на
открытом ключе получателя?

Интересно как это реализовано в КриптоПро.NET, ведь SymmetricAlgorithm подразумевает работу с явным значением
сессионного ключа как массива байтов, причем отдельно от вектора инициализации.

Offline Максим Коллегин  
#4 Оставлено : 13 февраля 2018 г. 15:34:29(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
Верно, а реализацию в .NEТ можете посмотреть сами - там мы разбираем собсвенные зашифрованные ключи. Подобный код есть и на форуме, но использовать этот код в боевых приложениях без дополнительных исследований не рекомендуется.

Отредактировано пользователем 14 февраля 2018 г. 9:29:03(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в техподдержке
thanks 1 пользователь поблагодарил Максим Коллегин за этот пост.
zhdamorev оставлено 13.02.2018(UTC)
Offline zhdamorev  
#5 Оставлено : 13 февраля 2018 г. 15:40:49(UTC)
zhdamorev

Статус: Новичок

Группы: Участники
Зарегистрирован: 06.02.2018(UTC)
Сообщений: 5
Мужчина
Российская Федерация
Откуда: Санкт-Петербург

Сказал «Спасибо»: 1 раз
Ясно, спасибо, возможно придётся отказаться от этой заманчивой идеи реализовывать шифрование используя абстракции .NET

Кстати буквально сегодня нашёл на гитхабе подобную интересную реализацию:
https://github.com/AlexMAS/GostCryptography
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.