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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline ShadowRNB  
#1 Оставлено : 6 марта 2023 г. 1:23:49(UTC)
ShadowRNB

Статус: Участник

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

Сказал «Спасибо»: 5 раз
Добрый день! Поставлена задача создать 2 приложения. Первое приложение генерит ключевую пару без создания запроса на сертификат на токен. Второе приложение создаёт запрос на сертификат на основании уже созданной ключевой пары в первом приложении. Если кто сталкивался, подскажите пожалуйста куда копать или может есть пример на .Net? Просьба без флуда, а зачем вам это? и почему? Надо :) Через командную строку тоже известно как. Заранее спасибо!

Отредактировано пользователем 6 марта 2023 г. 1:24:27(UTC)  | Причина: Не указана

Offline TolikTipaTut1  
#2 Оставлено : 8 марта 2023 г. 21:30:37(UTC)
TolikTipaTut1

Статус: Активный участник

Группы: Участники
Зарегистрирован: 05.07.2018(UTC)
Сообщений: 467

Сказал(а) «Спасибо»: 43 раз
Поблагодарили: 69 раз в 61 постах
Для этого нужно либо покупать и использовать КриптоПро .Net (примеры там же есть), или же пользоваться низкоуровневыми функциями MS CryptoAPI.

Ветка КриптоПро .Net тут.
Для генерации ключа путем вызова низкоуровневых функций потребуется AlgID. Ниже powershell скрипт, который выводит их для провайдера с ProvType 80 (Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider):

Код:
$lib = @"
        [DllImport("/opt/cprocsp/lib/amd64/libcapi20.so.4.0.5", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptAcquireContextA(
            ref IntPtr phProv,
            string pszContainer,
            string pszProvider,
            uint dwProvType,
            Int64 dwFlags
        );

        [DllImport("/opt/cprocsp/lib/amd64/libcapi20.so.4.0.5", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptGetProvParam(
            IntPtr hProv,
            uint dwParam,
            byte[] pbProvData,
            ref uint pdwProvDataLen, 
            uint dwFlags
        );

        [DllImport("/opt/cprocsp/lib/amd64/libcapi20.so.4.0.5", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptGenKey(
            IntPtr phProv,
            int Algid,
            int dwFlags,
            ref IntPtr phKey
        );

        [DllImport("/opt/cprocsp/lib/amd64/libcapi20.so.4.0.5", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptDestroyKey(
            IntPtr hKey 
        );

        [DllImport("/opt/cprocsp/lib/amd64/libcapi20.so.4.0.5", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptReleaseContext(
            IntPtr phProv,
            int flags
        );
"@

Add-Type -MemberDefinition $lib -Namespace PKI -Name CSP

[IntPtr] $phProv = [IntPtr]::Zero
[PKI.CSP]::CryptAcquireContextA(
    [ref]$phProv,
    $null,
    "Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider",
    80,
    (0xf0000000)
) | Out-Null
[byte[]]$pbProvData = $null
[int]$pbProvDataLen = 0
$flag = [PKI.CSP]::CryptGetProvParam($phProv, 0x16, $pbProvData, [ref]$pbProvDataLen, 0x1)
$algs = [System.Collections.ArrayList]::new()
while ($flag) {
    $algInfo = "" | Select-Object AlgName, DefaultLength, MinLength, MaxLength, Protocols, LongName, AlgID
    #Получаю байтики
    $pbProvData = [byte[]]::new($pbProvDataLen)
    $flag = [PKI.CSP]::CryptGetProvParam($phProv, 0x16, $pbProvData, [ref]$pbProvDataLen, 0x2)
    if ($flag -eq $false) {
        break;
    }
    
    # Начинаю парсить вывод согласно https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-prov_enumalgs_ex
    $NameLength = [System.BitConverter]::ToInt32($pbProvData[20..23],0)
    $algInfo.AlgName = [System.Text.Encoding]::ASCII.GetString($pbProvData[24..(24 + ($NameLength - 2))])
    $LongNameLength = [System.BitConverter]::ToInt32($pbProvData[44..47],0)
    $algInfo.LongName = [System.Text.Encoding]::ASCII.GetString($pbProvData[48..(48 + ($LongNameLength - 2))])
    $algInfo.DefaultLength = [System.BitConverter]::ToInt32($pbProvData[4..7],0)
    $algInfo.MinLength = [System.BitConverter]::ToInt32($pbProvData[8..11],0)
    $algInfo.MaxLength = [System.BitConverter]::ToInt32($pbProvData[12..15],0)
    $algInfo.Protocols = $pbProvData[16..19]
    $algInfo.AlgID = [System.BitConverter]::ToInt32($pbProvData[0..3],0)
    [void]$algs.Add($algInfo)
    
}
$algs | Format-Table | Out-Host
[PKI.CSP]::CryptReleaseContext($phProv, 0) | Out-Null


Пример вывода:
Код:
AlgName             DefaultLength MinLength MaxLength Protocols    LongName                             AlgID
-------             ------------- --------- --------- ---------    --------                             -----
GR 34.11-2012 256             256       256       256 {0, 0, 0, 0} GOST R 34.11-2012 256                32801
GR 34.10-2012 256             512       512       512 {0, 0, 0, 0} GOST R 34.10-2012 256                11849
DH 34.10-2012 256             512       512       512 {0, 0, 0, 0} GOST R 34.10-2012 256 DH             43590
DH 34.10-2012 256             512       512       512 {0, 0, 0, 0} GOST R 34.10-2012 256 DH             43591
GOST 28147-89 MAC              32         8        32 {0, 0, 0, 0} GOST 28147-89 MAC                    32799
GR 34.12-15 M                 256       256       256 {0, 0, 0, 0} GOST R 34.12-2015 64 Magma           26160
GR 34.12-15 K                 256       256       256 {0, 0, 0, 0} GOST R 34.12-2015 128 Kuznyechik     26161
GR 34.13-15 M MAC              64         8        64 {0, 0, 0, 0} GOST R 34.13-2015 64 Magma MAC       32828
GR 34.13-15 K MAC             128         8       128 {0, 0, 0, 0} GOST R 34.13-2015 128 Kuznyechik MAC 32829
GR34.11-12 256 HMAC           256       256       256 {0, 0, 0, 0} GOST R 34.11-2012 256 HMAC           32820

Отредактировано пользователем 8 марта 2023 г. 21:31:23(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил TolikTipaTut1 за этот пост.
ShadowRNB оставлено 09.03.2023(UTC)
Offline Андрей *  
#3 Оставлено : 9 марта 2023 г. 0:32:35(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,507
Мужчина
Российская Федерация

Сказал «Спасибо»: 554 раз
Поблагодарили: 2251 раз в 1756 постах
через CryptAcquireContext (hCSP ..., CRYPT_NEWKEYSET) - создать контейнер, ключи...

CryptGetProvParam(hCSP, PP_UNIQUE_CONTAINER
CryptGenKey(hCSP, KeyType, flag, .. )

запомнить имя контейнера и использовать потом для запроса

CryptAcquireContext (hCSP ..., 0)


генерация запроса (двойной вызов процедур там где он нужен с выделением памяти - пропущен):
закодировать структуры в CertNameInfo
CryptEncodeObject( ENCODING_TYPE, X509_NAME, CertNameInfo,...)
...
CryptEncodeObject( ENCODING_TYPE, X509_CERT_POLICIES POLICIES_INFO, ..
CryptEncodeObject( ENCODING_TYPE, X509_ENHANCED_KEY_USAGE, CertEnhKeyUsage ..
CryptEncodeObjectEx(X509_ASN_ENCODING, X509_KEY_USAGE, KeyUsage ...
CryptExportPublicKeyInfo(hCSP, KeyType,..
...
CryptSignAndEncodeCertificate(hCSP, KeyType, ENCODING_TYPE, X509_CERT_REQUEST_TO_BE_SIGNED, certReqInfo, sigAlg, .. signedReq)

записать signedReq - в файл p10\req


Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
ShadowRNB оставлено 09.03.2023(UTC)
Offline TolikTipaTut1  
#4 Оставлено : 9 марта 2023 г. 0:40:41(UTC)
TolikTipaTut1

Статус: Активный участник

Группы: Участники
Зарегистрирован: 05.07.2018(UTC)
Сообщений: 467

Сказал(а) «Спасибо»: 43 раз
Поблагодарили: 69 раз в 61 постах
А зачем после вызова CryptAcquireContext с флагом создания ключа и именем контейнера вызывать CryptGetProvParam? Сразу же можно CryptGenKey ...
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.