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

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline valerkambt  
#1 Оставлено : 29 марта 2021 г. 10:17:14(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Вот так получаю серт с помощью имени контейнера

Код:
CryptAcquireContext(&hContainer, (LPCSTR)containerName.UTF8String, NULL, PROV_GOST_2012_256, 0))


Беру так же ключ CryptGetKeyParam(key, KP_CERTIFICATE, 0, , 0);

И назначю контексту сертификата структуру CRYPT_KEY_PROV_INFO

Сертификат готов

Далее

Функция расшифровки CryptDecryptMessage принимает

Код:
CRYPT_DECRYPT_MESSAGE_PARA decryptPara;
    decryptPara.cCertStore = 1;


И тут нужен дескриптор стора HCERTSTORE. Вопрос где его взять? У полученного контекста серта его нет.

Я пытался добавить сертификат в стор с помощью

Код:
CertAddCertificateContextToStore


Серт добавляется, но функция CryptDecryptMessage выполняется с ошибкой, видимо потому что серт добавился без контейнера.

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

Код:
CryptAcquireContext(
            &hCryptProv,                 // handle to the CSP
            MyKeyContainer,                  // container name
            NULL,                        // use the default provider
            PROV_GOST_2012_256,                // provider type
            CRYPT_NEWKEYSET)                             // flag values
            )

Но и этого мне почему то не удалось - «Create container failed»

Отредактировано пользователем 29 марта 2021 г. 10:17:57(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#2 Оставлено : 29 марта 2021 г. 18:06:54(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
Порядок действий на первый взгляд верный, кроме последнего действия, конечно же. Приведите побольше кода, лучше законченный пример.

Отредактировано пользователем 29 марта 2021 г. 18:07:42(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в техподдержке
Offline valerkambt  
#3 Оставлено : 30 марта 2021 г. 7:33:00(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

вот так открываю стор

Код:
- (void)initCryptoStore{
    _hMemStore = CertOpenSystemStore(self.hCryptProv,
                                      [@"MY" cStringUsingEncoding:NSASCIIStringEncoding]);
    
    NSLog(@"%@", self.hCryptProv);
}


Создание серта из имени контейнера

Код:
- (instancetype) initWithContainer:(NSString*)containerName {
    
    HCRYPTPROV  hContainer = 0;
    
    if (CryptAcquireContext(&hContainer, (LPCSTR)containerName.UTF8String, NULL, PROV_GOST_2012_256, 0)){
    
        HCRYPTKEY key = 0;
        DWORD pdwCertLen = 0;
        CSP_BOOL    bResult = 0;
        
        DWORD keyType = AT_KEYEXCHANGE;
        
        CryptGetUserKey(hContainer, keyType, &key);
        
        CryptGetKeyParam(key, KP_CERTIFICATE, 0, &pdwCertLen, 0);
        
        BYTE *pbDecoded = (BYTE *) malloc(pdwCertLen);
        
        bResult = CryptGetKeyParam(key,
                                   KP_CERTIFICATE,
                                   pbDecoded,
                                   &pdwCertLen,
                                   0);
        
        NSData *datacert = [NSData dataWithBytes:pbDecoded length:pdwCertLen];
        
        BYTE *pbCertEncoded = (BYTE*) [datacert bytes];
        DWORD cbCertEncoded = (DWORD) [datacert length];
        DWORD dwCertEncodingType = X509_ASN_ENCODING |
        PKCS_7_ASN_ENCODING;
        
        PCCERT_CONTEXT cert = CertCreateCertificateContext(/*IN DWORD*/ dwCertEncodingType,
                                                           /*IN const BYTE * */ pbCertEncoded,
                                                           /*IN DWORD*/ cbCertEncoded);
        
        BYTE  pbData[1000];
        DWORD cbData = 1000;
        
        HCRYPTPROV hCryptProv;
        CryptAcquireContext(&hCryptProv, NULL, NULL, 75, CRYPT_VERIFYCONTEXT);
        
        if(CryptGetProvParam(
            hContainer,
            PP_USER_CERTSTORE,
            pbData,
            &cbData,
            0)){
            printf("CryptGetProvParam succeeded.\n");
            printf("Provider name: %s\n", pbData);
        }
        else {
            printf("Error reading CSP name. \n");
        }
        
        DWORD cbProvName;
        LPWSTR pbProvName = NULL;
        DWORD rv = ERROR_SUCCESS;
        
        if(!CryptGetDefaultProviderW(
            kGostProvType,
            NULL,
            CRYPT_MACHINE_DEFAULT,
            NULL,
            &cbProvName))
        {
            printf("Error getting the length of the default provider name.");
            rv = CSP_GetLastError();
            //goto free_cert_context;
        }
        
        pbProvName = new wchar_t[cbProvName];
        if(!CryptGetDefaultProviderW(
            kGostProvType,
            NULL,
            CRYPT_MACHINE_DEFAULT,
            pbProvName,
            &cbProvName))
        {
            printf("Error getting the length of the default provider name.");
            rv = CSP_GetLastError();
           // goto free_prov_name;
        }
        
        LPWSTR wContName = NULL;
        LPCSTR cName = (LPCSTR)containerName.UTF8String;
        
        wContName = new wchar_t[strlen(cName)+1];
        mbstowcs (wContName, cName, strlen(cName)+1);
        
        CRYPT_KEY_PROV_INFO KeyProvInfo;
        
        KeyProvInfo.pwszContainerName = wContName;
        KeyProvInfo.pwszProvName = pbProvName;
        KeyProvInfo.dwProvType = kGostProvType;
        KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
        KeyProvInfo.dwFlags = 0;
        KeyProvInfo.cProvParam = 0;
        KeyProvInfo.rgProvParam = NULL;
        
        if (!CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, (void *) &KeyProvInfo)) {
            printf("CertSetCertificateContextProperty error");
            rv = CSP_GetLastError();
           // goto free_wcont_name;
        }
        
       // PCCERT_CONTEXT certDup = 0;
      //  certDup = CertDuplicateCertificateContext(cert);
        
        
        self = [super init];
        if (self) {
            self.cryptoProCert = [[CryptoProCertInfo alloc] initWithCert:cert
                                                                    prov:hContainer
                                                                    type:keyType];
          // self.cryptoProCert.store = hMemStore;
            self.containerName = containerName;
        }
        return self;
    }
    
    return nil;
}


Импорт серта в стор

Код:
- (BOOL)importCertCtx:(CryptoCertWrappper*)cert{
    
    HCERTSTORE hCertStore = _hMemStore;
    DWORD dwAddDisposition = CERT_STORE_ADD_ALWAYS;
    
    BOOL result = CertAddCertificateContextToStore(/*HCERTSTORE*/ hCertStore,
                                            /*PCCERT_CONTEXT*/  cert.cryptoProCert.cert,
                                            /*DWORD*/ dwAddDisposition,
                                            /*OUT OPTIONAL PCCERT_CONTEXT*/ NULL);
    DWORD error = ERROR_SUCCESS;
    if (!result) {
        error = CSP_GetLastError();
    } else {
        cert.cryptoProCert.store = self.hMemStore;
    }

    return result;
}


Расшифровка

Код:
+ (NSData *)decryptData:(NSData *)data rghCertStore:(HCERTSTORE *)hMemStore error:(NSError**) error {
    
    CRYPT_DECRYPT_MESSAGE_PARA decryptPara;
    
    decryptPara.cbSize = sizeof(PCRYPT_DECRYPT_MESSAGE_PARA);
    decryptPara.dwMsgAndCertEncodingType =  PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
    decryptPara.cCertStore = 1;
    decryptPara.rghCertStore = &hMemStore;
    
    BYTE *pbDecrypted;
    DWORD cbDecrypted = 0;
    
    BOOL res = CryptDecryptMessage(&decryptPara,
                                   [data bytes],
                                   (DWORD) [data length],
                                   NULL,
                                   &cbDecrypted,
                                   NULL);
    
    if (!res) {
        DWORD err = CSP_GetLastError();
        
        NSString *errorStr = [NSString stringWithFormat: @"Cannot decrypt message: %d", err];
        
        *error = [NSError errorWithDomain:@""
                                    code:err
                                userInfo:@{NSLocalizedDescriptionKey:errorStr}];
    
        return nil;
    }
    
    pbDecrypted = calloc(1, cbDecrypted);
    res = CryptDecryptMessage(&decryptPara,
                              [data bytes],
                              (DWORD) [data length],
                              pbDecrypted,
                              &cbDecrypted,
                              NULL);
    
    if (!res) {
        DWORD err = CSP_GetLastError();
        NSString *errorStr = [NSString stringWithFormat: @"Cannot decrypt message: %d", err];
        
        *error = [NSError errorWithDomain:@""
                                    code:err
                                userInfo:@{NSLocalizedDescriptionKey:errorStr}];
        return nil;
    }
    
    NSData *decryptedData = [NSData dataWithBytes:pbDecrypted length:cbDecrypted];
    
    free(pbDecrypted);
    
    return decryptedData;
}


...получаю code: 2148081676

Не удается найти сертификат и закрытый ключ для расшифровки.

Отредактировано пользователем 30 марта 2021 г. 7:35:38(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#4 Оставлено : 30 марта 2021 г. 7:53:44(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
А сертификат точно тот, в адрес которого зашифровано сообщение?
Если у вас проходит вызов PP_USER_CERTSTORE, то это хранилище и можно использовать для расшифровки.
А иначе имя и тип криптопровайдера нужно получать через PP_NAME и PP_PROVTYPE
Знания в базе знаний, поддержка в техподдержке
Offline Максим Коллегин  
#5 Оставлено : 30 марта 2021 г. 7:58:13(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
А в функции importCertCtx _hMemStore и hMemStore — это один и тот же объект?
Немного смущает название переменной для хранилища “My”
Знания в базе знаний, поддержка в техподдержке
Offline valerkambt  
#6 Оставлено : 30 марта 2021 г. 8:40:51(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

hMemStore - да это один контекст стора ? “My” - а разве есть разница как назвать хранилище? Это из сэмплов взялось.
Offline Максим Коллегин  
#7 Оставлено : 30 марта 2021 г. 8:42:52(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
А по предыдущему комментарию?
Знания в базе знаний, поддержка в техподдержке
Offline valerkambt  
#8 Оставлено : 30 марта 2021 г. 8:49:09(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Цитата:
А сертификат точно тот, в адрес которого зашифровано сообщение?
Если у вас проходит вызов PP_USER_CERTSTORE, то это хранилище и можно использовать для расшифровки.
А иначе имя и тип криптопровайдера нужно получать через PP_NAME и PP_PROVTYPE


тут не понял, конкретно про "это хранилище и можно использовать для расшифровки." это же это какое? я же не получаю дескриптор стора. Раскалите подробнее пожалуйста

Отредактировано пользователем 30 марта 2021 г. 8:49:57(UTC)  | Причина: Не указана

Offline valerkambt  
#9 Оставлено : 30 марта 2021 г. 8:53:07(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

УРа я понял) все ща попробую нашел сэмпл. с CryptGetProvParam(hProv, PP_USER_CERTSTORE, (PBYTE)&hCertStore, &size, 0);
Offline valerkambt  
#10 Оставлено : 30 марта 2021 г. 9:36:33(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Автор: Максим Коллегин Перейти к цитате
А сертификат точно тот, в адрес которого зашифровано сообщение?
Если у вас проходит вызов PP_USER_CERTSTORE, то это хранилище и можно использовать для расшифровки.
А иначе имя и тип криптопровайдера нужно получать через PP_NAME и PP_PROVTYPE



на вызов

Код:
if(CryptGetProvParam(
            hContainer,
            PP_USER_CERTSTORE,
            pbData,
            &cbData,
            0)){
            printf("CryptGetProvParam succeeded.\n");
            printf("Provider name: %s\n", pbData);
        }
        else {
            printf("Error reading CSP name. \n");
            rv = CSP_GetLastError();
            printf("CryptGetProvParam(PP_USER_CERTSTORE): %x\n", rv);
        }


я получаю <capi20>0x16d5cb000:CryptGetProvParam!failed: LastError = 0x0 (:1440)

к сожалению мне могу найти что значит сей код ошибки*
Offline Максим Коллегин  
#11 Оставлено : 30 марта 2021 г. 9:45:57(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
Этот вызов работает не для всех версий CSP.
Какая у вас?
Знания в базе знаний, поддержка в техподдержке
Offline valerkambt  
#12 Оставлено : 30 марта 2021 г. 9:53:38(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Автор: Максим Коллегин Перейти к цитате
Этот вызов работает не для всех версий CSP.
Какая у вас?


CryptoPro CSP 5.0 build 11823

Отредактировано пользователем 30 марта 2021 г. 9:57:13(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#13 Оставлено : 30 марта 2021 г. 10:08:13(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
Повторю вопрос, сообщение точно зашифровано этим сертификатом?
Попробуйте расшифровать данные с помощью csptest -sfenc, проверив, что сертификат есть в хранилище my
Так же можете попробовать установить последнюю версию CSP 5.0 и попробовать расшифровать с помощью cptools.
Знания в базе знаний, поддержка в техподдержке
Offline valerkambt  
#14 Оставлено : 30 марта 2021 г. 10:26:19(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Автор: Максим Коллегин Перейти к цитате
Повторю вопрос, сообщение точно зашифровано этим сертификатом?
Попробуйте расшифровать данные с помощью csptest -sfenc, проверив, что сертификат есть в хранилище my
Так же можете попробовать установить последнюю версию CSP 5.0 и попробовать расшифровать с помощью cptools.


Да да этим.

Мне не очень сподручно запускать команды терминала из Objective C на iOS
для таких проверок.

У меня же основная проблема в том что я не могу получить HCERTSTORE со смарт карты для расшифровки. именинно поэтому я добавляю сертификат в лока
льный стор. Я делаю это правильно? все должно работать?

после добавления в стор я делаю

Код:
 PCCERT_CONTEXT pDesiredCert = NULL;
     pDesiredCert = CertFindCertificateInStore(
            _hCertStore,
           TYPE_DER,          
           0,     
           CERT_FIND_SUBJECT_STR,    
           cEmail,
            NULL);


и сертификат в сторе ТОЧНО ЕСТЬ.

Как узнать с какой версии работает ->

Код:
CryptGetProvParam(
            hContainer,
            PP_USER_CERTSTORE,
            pbData,
            &cbData,
            0)){
            printf("CryptGetProvParam succeeded.\n");
            printf("Provider name: %s\n", pbData);
        }

Отредактировано пользователем 30 марта 2021 г. 10:41:07(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#15 Оставлено : 30 марта 2021 г. 10:41:56(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
Прошу прощения, не было информации про то, что работа на iOS.
PP_USER_CERTSTORE на Unix работает только при указании флага CP_CRYPT_SERIALIZED_STORE, и целом, оно вам не очень поможет. С нулевым кодом ошибки хотелось бы разобраться - включите пожалуйста аудит в config.ini:
Код:
[debug]
csp=63
capi10=63
capi20=63

Это для CSP 5.0.11998

Я всё-таки буду просить подготовить законченный пример приложения, чтобы мы смогли найти ошибку.
Знания в базе знаний, поддержка в техподдержке
Offline valerkambt  
#16 Оставлено : 30 марта 2021 г. 10:52:54(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Автор: Максим Коллегин Перейти к цитате
Прошу прощения, не было информации про то, что работа на iOS.
PP_USER_CERTSTORE на Unix работает только при указании флага CP_CRYPT_SERIALIZED_STORE, и целом, оно вам не очень поможет. С нулевым кодом ошибки хотелось бы разобраться - включите пожалуйста аудит в config.ini:
Код:
[debug]
csp=63
capi10=63
capi20=63

Это для CSP 5.0.11998

Я всё-таки буду просить подготовить законченный пример приложения, чтобы мы смогли найти ошибку.


Хорошо я сейчас обновлю версию КриптоПРо и подготовлю пример. Но мне пожалуйста хотелось бы получить ответ -

я правильно добавляю сертификат в стор полученный из Рутокена? Разве не нужно для расшифровки переносить его вместе с контейнером?
Offline valerkambt  
#17 Оставлено : 30 марта 2021 г. 10:55:27(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Автор: Максим Коллегин Перейти к цитате
Порядок действий на первый взгляд верный, кроме последнего действия, конечно же. Приведите побольше кода, лучше законченный пример.


Кроме последнего действия это какого?
Offline valerkambt  
#18 Оставлено : 30 марта 2021 г. 10:58:24(UTC)
valerkambt

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

Группы: Участники
Зарегистрирован: 24.10.2020(UTC)
Сообщений: 17
Российская Федерация

Автор: Максим Коллегин Перейти к цитате
А сертификат точно тот, в адрес которого зашифровано сообщение?
Если у вас проходит вызов PP_USER_CERTSTORE, то это хранилище и можно использовать для расшифровки.
А иначе имя и тип криптопровайдера нужно получать через PP_NAME и PP_PROVTYPE


"А иначе имя и тип криптопровайдера нужно получать через PP_NAME и PP_PROVTYPE" можно подробнее об этом ? как мне использовать имя и тип провайдера для расшифровки?
Offline Максим Коллегин  
#19 Оставлено : 30 марта 2021 г. 13:48:49(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
Автор: valerkambt Перейти к цитате

Кроме последнего действия это какого?

вот этого:

Автор: valerkambt Перейти к цитате

Код:
CryptAcquireContext(
            &hCryptProv,                 // handle to the CSP
            MyKeyContainer,                  // container name
            NULL,                        // use the default provider
            PROV_GOST_2012_256,                // provider type
            CRYPT_NEWKEYSET)                             // flag values
            )

Но и этого мне почему то не удалось - «Create container failed»




Имя и тип нужно указывать в структуре CRYPT_KEY_PROV_INFO при создании ссылки на контейнер.
Знания в базе знаний, поддержка в техподдержке
Offline Максим Коллегин  
#20 Оставлено : 30 марта 2021 г. 17:37:41(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
Автор: valerkambt Перейти к цитате

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


Правильно, контейнер остаётся на Рутокен, в контекст сертификата записывается ссылка на него.


На текущей версии CSP 5.0 нулевой код ошибки в PP_USER_CERTSTORE у меня не воспроизводится (на macOS).

Отредактировано пользователем 30 марта 2021 г. 17:39:09(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в техподдержке
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.