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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Серёня  
#1 Оставлено : 6 марта 2014 г. 12:50:34(UTC)
Серёня

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

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

Сказал «Спасибо»: 2 раз
Здравствуйте.
Мне необходимо написать программу, с помощью которой пользователи будут подписывать некий документ своей ЭЦП. Соответственно пользователь, подписывающий документ, не один и у каждого из них будет съемный носитель с контейнером ключей.
Платформа - Linux. CSP версии v3.6.5365 КС2 Release Ver:3.6.7777. Опыта работы с CSP нет.

Сейчас я пытаюсь получить сертификат из контейнера ключей со съемного носителя для всех доступных контейнеров, делаю вот так

Код:
// Получаем дескриптор криптопровайдера
HCRYPTPROV hProv = 0;
if(!CryptAcquireContext(&hProv, NULL, NULL, CSP_PROV_TYPE, CRYPT_VERIFYCONTEXT)) {
    HandleError("CryptAcquireContext failed");
}

DWORD fParam = CRYPT_FIRST;
DWORD cnt = 0;
DWORD size = 1000;
BYTE ContName[1000];
BYTE* pbCertBlob = 0;
DWORD dwCertBlob = 0;
PCCERT_CONTEXT certificate = 0;

// Перебираем все доступные контейнеры
while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, ContName, &size, fParam)) {
    printf("Container name: %s\n", (char*) ContName);
    fParam = CRYPT_NEXT;
    cnt++;
    HCRYPTKEY hKey;
    HCRYPTPROV hProv2;
    char* name = new char[size];
    strcpy(name, (char*) ContName);
    printf("name: %s\n", name);

    // Получаем дескриптор контейнера
    // Вот тут, кстати, вопрос. Если использовать hProv для которого указано CRYPT_VERIFYCONTEXT,
    // то CryptGetUserKey не находи ключи, возвращает 0x8009000d
    // Поэтому получаем новый дескриптор провайдера.
    // Так и надо, или я что-то делаю не так?
    CryptAcquireContext(&hProv2, name, NULL, CSP_PROV_TYPE, NULL);

    // Получение дескриптора открытого ключа
    if (CryptGetUserKey(hProv2, CSP_KEY_TYPE, &hKey)) {
        printf("CryptGetUserKey success! Type: CSP_KEY_TYPE: %d\n", CSP_KEY_TYPE);

        // Получение сертификата ключа из контейнера
        // Сначала получаем размер
//////Вот тут возникает ошибка 0x8010002c			
        if (CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &dwCertBlob, NULL)) {
            if (pbCertBlob = new BYTE[dwCertBlob]) {

                // теперь сам сертификат
                if (CryptGetKeyParam(hKey, KP_CERTIFICATE, pbCertBlob, &dwCertBlob, NULL)) {
                    printf("CryptGetKeyParam success!\n");
                    CRYPT_KEY_PROV_INFO key;
                    //key.pwszContainerName = name;
                    //key.pwszProvName = CSP_PROV_NAME;
                    key.dwProvType = CSP_PROV_TYPE;
                    key.dwFlags = NULL;
                    key.cProvParam = NULL;
                    key.rgProvParam = NULL;
                    key.dwKeySpec = CSP_KEY_TYPE;
                    if (certificate = CertCreateCertificateContext(
                            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                            pbCertBlob,
                            dwCertBlob)) {							
                    } else {
                        printf("CertCreateCertificateContext failed!.\n");
                        DWORD err = GetLastError();
                        printf("Error number     : 0x%x\n", err);
                    }
                } else {
                    printf("CryptGetKeyParam 2 failed!\n");
                }
            } else {
                printf("pbCertBlob = new BYTE[dwCertBlob]    - failed!\n");
            }
        } else {
        printf("CryptGetKeyParam 1 failed!\n");
                DWORD err = GetLastError();
                printf("Error number     : 0x%x\n", err);
            }
    } else {
        printf("CryptGetUserKey failed. Type: CSP_KEY_TYPE: %d\n", CSP_KEY_TYPE);
        DWORD err = GetLastError();
        printf("Error number     : 0x%x\n", err);
    }
    delete[] name;
}


Вобщем вопрос, что это за ошибка 0x801002c и что я делаю не так?
Offline Василий Дементьев  
#2 Оставлено : 6 марта 2014 г. 13:25:35(UTC)
Василий Дементьев

Статус: Администратор

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

Поблагодарили: 6 раз в 5 постах
Ошибка 0x8010002C означает "Требуемый сертификат не существует".
Т.е. в контейнере нет сертификата.
Это нормальная ситуация - сертификат не всегда устанавливают в ключевой контейнер.
Offline Серёня  
#3 Оставлено : 6 марта 2014 г. 15:11:20(UTC)
Серёня

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

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

Сказал «Спасибо»: 2 раз
Правильно ли я понимаю, что без сертификата не получится получить закрытый ключ электронной подписи? Или все-таки это возможно?
Offline Юрий  
#4 Оставлено : 6 марта 2014 г. 15:49:46(UTC)
Юрий

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

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

Сказал «Спасибо»: 3 раз
Поблагодарили: 93 раз в 67 постах
Автор: Серёня Перейти к цитате
Правильно ли я понимаю, что без сертификата не получится получить закрытый ключ электронной подписи? Или все-таки это возможно?

Сертификаты и ключи связаны очень искуственно. Это разные сущности.
Так что да, без сертификата можно получить закрытый ключ.
С уважением,
Юрий Строжевский
Offline Серёня  
#5 Оставлено : 6 марта 2014 г. 16:05:40(UTC)
Серёня

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

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

Сказал «Спасибо»: 2 раз
Ну тогда вопрос напрашивается сам собой. Как получить закрытый ключ из контейнера без сертификата?
Сей час воспользовался тестовым УЦ (https://www.cryptopro.ru/certsrv/) и мой пример заработал. Но в таком случае не хотелось бы привязываться к сертификату, если есть такая возможность.
Offline Юрий  
#6 Оставлено : 6 марта 2014 г. 16:17:26(UTC)
Юрий

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

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

Сказал «Спасибо»: 3 раз
Поблагодарили: 93 раз в 67 постах
Автор: Серёня Перейти к цитате
Ну тогда вопрос напрашивается сам собой. Как получить закрытый ключ из контейнера без сертификата?
Сей час воспользовался тестовым УЦ (https://www.cryptopro.ru/certsrv/) и мой пример заработал. Но в таком случае не хотелось бы привязываться к сертификату, если есть такая возможность.

По-правильному "получение закрытого ключа" называется "экспорт". Так что смотрите стандартные примеры по экспорту ключей во внешние контейнеры.
С уважением,
Юрий Строжевский
Offline Серёня  
#7 Оставлено : 6 марта 2014 г. 16:41:37(UTC)
Серёня

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

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

Сказал «Спасибо»: 2 раз
Когда я формировал ключи в тестовом СЦ, там была галочка "Пометить ключ как экспортируемый". Правильно ли я понял, если ее не поставить, то экспортировать ключ не удастся?
Offline Юрий  
#8 Оставлено : 6 марта 2014 г. 16:46:30(UTC)
Юрий

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

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

Сказал «Спасибо»: 3 раз
Поблагодарили: 93 раз в 67 постах
Да, правильно.
Однако посмотрев первый пост я думаю, что скорее всего вам нужна функция "CryptAcquireContext".
С уважением,
Юрий Строжевский
thanks 1 пользователь поблагодарил Юрий за этот пост.
Серёня оставлено 11.03.2014(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (3)
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.