Проверить доступ к профайлу на С++

Автор Abzal, 24 Декабрь 2013, 15:58:27

« предыдущая тема - следующая тема »

0 Пользователей и 1 Гость просматривают эту тему.

Вниз

Abzal

Добрый день!

В примерах по использованию ТумарCSP есть:
KeyStore store = KeyStore.getInstance("GKS", "GAMMA");
                String prof = "profile://eToken";
                store.load(new ByteArrayInputStream(prof.getBytes()), "1234567890".toCharArray());

Но не могу найти пример на с++
Как проверить доступ к профайлу на с++?

Sergey

Добрый день.

Это можно сделать функцией:
CPAcquireContext(&hProv,"profile://eToken",0,NULL)
Все примеры есть в SDK.

Abzal

24 Декабрь 2013, 16:40:37 #2 Последнее редактирование: 24 Декабрь 2013, 17:01:52 от Abzal
Сергей, а как узнать соответствие пароля?

Sergey

Для загрузки ключей с паролем можно воспользоваться функцией:

int createURL(char *name, char *dev, char *user, char *pass, char *param, char *cont, int alg_exch, int alg_sign, char *profile){
  ContInfoEx *contInfoEx = NULL;
  DWORD cbData = 0;
  HCRYPTPROV hProv = 0;

  contInfoEx = new ContInfoEx;
  if (!contInfoEx) {
return 1;
  }
  memset(contInfoEx, 0, sizeof(ContInfoEx));
  strcpy(contInfoEx->name, name);
  strcpy(contInfoEx->dev, dev);
  strcpy(contInfoEx->user, user);
  strcpy(contInfoEx->pass, pass);
  strcpy(contInfoEx->param, param);
  strcpy(contInfoEx->cont, cont);
  contInfoEx->alg_exch = alg_exch;
  contInfoEx->alg_sign = alg_sign;
  cbData = sizeof(ContInfoEx);
  if(!CPAcquireContext(&hProv, NULL, CRYPT_VERIFYCONTEXT, NULL)){
delete contInfoEx;
return 2;
  }
  if(!CPGetProvParam(hProv, PP_PROF_TO_URL, (BYTE *)contInfoEx, &cbData, 0)){
delete contInfoEx;
CPReleaseContext(hProv, 0);
return 3;
  }
  strcpy(profile, contInfoEx->Url);
  delete contInfoEx;
  CPReleaseContext(hProv, 0);
  return 0;
}

Пример работы данной функции:

HCRYPTPROV hProv = 0;
char profile[512];
LoadTumarCSP(NULL);
int retCode = createURL("myprofile", "file", "test1priv", "6nhokm", "c:\\key\\", "pfx", 0xA045, 0xAA3A, profile);
if(retCode==0){
if(!CPAcquireContext(&hProv, profile, 0, NULL)){
  printf("error load key \n");
}else{
  printf("profile load \n");
          CPReleaseContext(hProv, 0);
        }
}


Abzal

Сергей, спасибо!

strcpy(contInfoEx->name, name);
  strcpy(contInfoEx->dev, dev);
  strcpy(contInfoEx->user, user);
  strcpy(contInfoEx->pass, pass);
  strcpy(contInfoEx->param, param);
  strcpy(contInfoEx->cont, cont);
  contInfoEx->alg_exch = alg_exch;
  contInfoEx->alg_sign = alg_sign;
1.А как можно узнать какой из заданных параметров неправильный?

if(!CPGetProvParam(hProv, PP_PROF_TO_URL, (BYTE *)contInfoEx, &cbData, 0)){
2.где можно посмотреть все значения dwParam, а то в SDK PP_PROF_TO_URL нету?

//Формируем класс хранилища ключей, будут доступны все профайлы криптопровайдера.
            KeyStore store = loadKeyStore();
            //Получение списка ключей
            Enumeration en = store.aliases();
            while (en.hasMoreElements()) {
                StoreObjectParam profParam = (StoreObjectParam) en.nextElement();
                System.out.println(profParam);
            }
3.на с++ как можно сформировать список ключей в профайле?



Sergey

1. Код должен быть построен таким образом, что бы неправильно задать можно  было только пароль.
2. Значения dwParam описаны в wincrypt.h и cptumar.h
3. Для перечисления всех ключей нужно выполнить
- cpGetProvParam с параметром PP_CNT_KEYS_COUNT (данная функция возвращает количество ключей)
- в цикле вызывать cpGetProvParam с параметром PP_ENUM_CNT_PRIV_KEYS первый вызов dwFlags с CRYPT_FIRST последующие с dwFlags = 0
   (данная функция возвращает структуру CNT_PRIVATE_KEY_EX с информацией о ключе).


Abzal

Сергей, а где описана структура CNT_PRIVATE_KEY_EX ?

Sergey

Все нужные структуры и параметры описаны в wincrypt.h и cptumar.h

Abzal

wincrypt.h и cptumar.h есть, но там нет структуры CNT_PRIVATE_KEY_EX

Sergey

Немного ошибся структура называется CNT_PRIVATE_KEY
typedef struct _CNT_PRIVATE_KEY {
HCRYPTKEY hKey;
ALG_ID    algID;
BOOL      exp;
DWORD     state;
CHAR     *szOID;
CHAR     *createTime;
DATA_BLOB serialNum;
DATA_BLOB publicKey;
CERT_BLOB certificate;
} CNT_PRIVATE_KEY;

Abzal

Сергей, спасибо, получилось!

А как сформировать подпись выбранным ключем из списка в контейнере, если в профайле имеется несколько ключевых пар?

Sergey

Для этого нужно сформировать URL на ключ по аналогии с примером в createURL.
В структуре ContInfo нужно заполнить поле serialNum.
Но следует помнить что если выбрать ключ на шифрование и при этом попытаться на нем подписать, то система все равно подпишет на ключе для подписи.

Abzal

Добрый день!

Цитата: Sergey от 25 Декабрь 2013, 15:52:53
3. Для перечисления всех ключей нужно выполнить
- cpGetProvParam с параметром PP_CNT_KEYS_COUNT (данная функция возвращает количество ключей)
- в цикле вызывать cpGetProvParam с параметром PP_ENUM_CNT_PRIV_KEYS первый вызов dwFlags с CRYPT_FIRST последующие с dwFlags = 0
   (данная функция возвращает структуру CNT_PRIVATE_KEY_EX с информацией о ключе).


Не получается перечислить все ключи, делаю так:
                  int dwFlags = CRYPT_FIRST;
                  do{
                        CNT_PRIVATE_KEY *key= new CNT_PRIVATE_KEY;
                        DWORD key_LEN = sizeof(ContInfoEx);
                        if (!ACPGetProvParam(hProv,PP_ENUM_CNT_PRIV_KEYS, (BYTE *)key, &key_LEN, dwFlags)) {
                                AnsiString str="Can't GetProvParam ";
                                DWORD LEN = AGetLastErrorCSP(hProv);
                                if(LEN==ERROR_NO_MORE_ITEMS)
                                        break;
                                throw Exception(str);
                        }else{
                                  dwFlags =0;
                                  String     createTime(key->createTime);
                                  String name="Создан: "+ createTime.SubString(1,4)+"-"+createTime.SubString(5,2)+"-"+createTime.SubString(7,2) ;
                                  certs_list->Items->Add(name);
                        }

                  }while(data!=NULL);

Показывает только один, хотя в конфигураторе вижу 4
В чем может быть проблема?

Sergey

Возможно из-за того что цикл do while выполняется один раз.

Abzal

Цикл выполняется 2 раза, на второй раз обрывается на
if(LEN==ERROR_NO_MORE_ITEMS)
                                        break;

Хотя ключевых пар в профайле 4

Вверх