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

Уведомление

Icon
Error

4 Страницы123>»
Опции
К последнему сообщению К первому непрочитанному
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,374
Мужчина
Откуда: КРИПТО-ПРО

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

Отредактировано пользователем 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,374
Мужчина
Откуда: КРИПТО-ПРО

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

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

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

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
А в функции 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,374
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 32 раз
Поблагодарили: 704 раз в 613 постах
А по предыдущему комментарию?
Знания в базе знаний, поддержка в техподдержке
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)

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