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

Уведомление

Icon
Error

3 Страницы123>
Опции
К последнему сообщению К первому непрочитанному
Offline dmitrigan  
#1 Оставлено : 3 марта 2015 г. 17:52:30(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
Добрый день, уважаемые гуру. Итак, есть считыватель и созданный на нем ключевой контейнер. Также к закрытому ключу создан сертификат пользователя, который привязан к закрытому ключу в контейнере и импортирован в личное хранилище сертификатов пользователя ОС.
Теперь мне необходимо - отобразить список сертификатов в личном хранилище пользователя.
Делаю при помощи CertEnumCertificatesInStore();
Сертификаты отображаются, все замечательно.
Теперь мне необходимо при выборе сертификата пользователем получить контейнер и носитель, на котором записаны закрытый и открытый ключ пользователя. Делаю это при помощи
CertGetCertificateContextProperty(). Использую при этом параметр CERT_KEY_PROV_INFO_PROP_ID.
Есть вопрос - в msdn описано, что при первом вызове вместо указателя на структуру CRYPT_KEY_PROV_INFO необходимо использовать нуль-значение. А тогда как правильно получить ссылку на контейнер и носитель. Заранее спасибо!
Offline Максим Коллегин  
#2 Оставлено : 3 марта 2015 г. 23:01:36(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 39 раз
Поблагодарили: 750 раз в 645 постах
После вызова выделить память, согласно возвращенному размеру, и вызвать еще раз. Такова семантика многих функций Windows.
Знания в базе знаний, поддержка в центре поддержки
thanks 1 пользователь поблагодарил Максим Коллегин за этот пост.
dmitrigan оставлено 14.03.2015(UTC)
Offline dmitrigan  
#3 Оставлено : 3 марта 2015 г. 23:11:32(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
спасибо, попробую двойной вызов.
Offline dmitrigan  
#4 Оставлено : 4 марта 2015 г. 10:07:09(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
Начинаю разбираться дальше, появляются вопросы. Вот код
Код:

procedure TEnumCertForm.EnumButtonClick(Sender: TObject);
var prov: HCRYPTPROV;
    store: HCERTSTORE;
    cont, stor: PChar;
    err: string;
    cert: PCCERT_CONTEXT;
    nameString: PChar;
    size: DWORD;
    nameBLOB: CERT_NAME_BLOB;
    encType: DWORD;
    pdwKeySpec:Dword;
    pfCallerFreeProvOrNCryptKey:Boolean;
    certkeyinfo:PCRYPT_KEY_PROV_INFO;
    datalen:Cardinal;
    par2:Cardinal;
    cert1:PCertContext;
    WS:AnsiString;
begin
encType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
if length(ContainerEdit.Text) = 0
then cont := nil
else
    begin
    err := ContainerEdit.Text;
    cont := StrAlloc(length(err) + 1);
    StrPCopy(cont, err);
    end;
if not CryptAcquireContext(prov, cont, nil, 75, 0)   //75 - íîìåð êðèïòîïðîâàéäåðà ÊðèïòîïðîCSP
then
    begin
    case int64(GetLastError) of
    ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
    ERROR_NOT_ENOUGH_MEMORY: err := 'ERROR_NOT_ENOUGH_MEMORY';
    NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
    NTE_BAD_KEYSET: err := 'NTE_BAD_KEYSET';
    NTE_BAD_KEYSET_PARAM: err := 'NTE_BAD_KEYSET_PARAM';
    NTE_BAD_PROV_TYPE: err := 'NTE_BAD_PROV_TYPE';
    NTE_BAD_SIGNATURE: err := 'NTE_BAD_SIGNATURE';
    NTE_EXISTS: err := 'NTE_EXISTS';
    NTE_KEYSET_ENTRY_BAD: err := 'NTE_KEYSET_ENTRY_BAD';
    NTE_KEYSET_NOT_DEF: err := 'NTE_KEYSET_NOT_DEF';
    NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
    NTE_PROV_DLL_NOT_FOUND: err := 'NTE_PROV_DLL_NOT_FOUND';
    NTE_PROV_TYPE_ENTRY_BAD: err := 'NTE_PROV_TYPE_ENTRY_BAD';
    NTE_PROV_TYPE_NO_MATCH: err := 'NTE_PROV_TYPE_NO_MATCH';
    NTE_PROV_TYPE_NOT_DEF: err := 'NTE_PROV_TYPE_NOT_DEF';
    NTE_PROVIDER_DLL_FAIL: err := 'NTE_PROVIDER_DLL_FAIL';
    NTE_SIGNATURE_FILE_BAD: err := 'NTE_SIGNATURE_FILE_BAD';
    else err := 'Unknown error';
    end;
    MessageDlg('Îøèáêà ñîçäàíèÿ êîíòåéíåðà: ' + err, mtError, [mbOK], 0);
    if cont <> nil then StrDispose(cont);
    exit;
    end;
err := CertStoreBox.Text;
RepMemo.Lines.Add('');
RepMemo.Lines.Add('====================');
RepMemo.Lines.Add('Contents of store ' + err);
RepMemo.Lines.Add('====================');
stor := StrAlloc(length(err) + 1);
StrPCopy(stor, err);
store := CertOpenSystemStore(prov, stor);
if store = nil then
   begin
   MessageDlg('Error opening store', mtError, [mbOK], 0);
   if cont <> nil then StrDispose(cont);
   StrDispose(stor);
   exit;
   end;
cert := CertEnumCertificatesInStore(store, nil);
nameString := StrAlloc(512);
while cert <> nil do
      begin
      RepMemo.Lines.Add('---------------');
      RepMemo.Lines.Add('Subject:');
      nameBLOB := cert^.pCertInfo^.Subject;

      size := CertNameToStr(encType, @nameBlob, CERT_SIMPLE_NAME_STR,nameString, 512);
      if size > 1 then
         RepMemo.Lines.Add(nameString)
      else
          RepMemo.Lines.Add('Error');
      RepMemo.Lines.Add('Issuer:');
      nameBLOB := cert^.pCertInfo^.Issuer;

      size := CertNameToStr(encType, @nameBlob, CERT_SIMPLE_NAME_STR, nameString, 512);
      if size > 1 then
         RepMemo.Lines.Add(nameString)
      else
          RepMemo.Lines.Add('Error');
          pdwkeySpec:=AT_Signature;
          pfCallerFreeProvOrNCryptKey:=true;

   par2:=CERT_KEY_PROV_INFO_PROP_ID;
      datalen:=0;
       CertGetCertificateContextProperty(cert, par2,nil,datalen) ;
       GetMem(certkeyinfo,datalen);  //Âûäåëåíèå ïàìÿòè
     CertGetCertificateContextProperty(cert, par2,@certkeyinfo,datalen);
     WS:= certkeyinfo^.pwszContainerName;
    RepMemo.Lines.add(WS);

    cert := CertEnumCertificatesInStore(store, cert);
      end;
if nameString<>nil then StrDispose(nameString);
if cont <> nil then StrDispose(cont);
StrDispose(stor);

if not CryptReleaseContext(prov, 0) then
   MessageDlg('Îøèáêà îñâîáîæäåíèÿ êîíòåêñòà - '+IntToStr(GetLastError), mtError, [mbOK], 0);
if not CertCloseStore(store, 0) then
   MessageDlg('Îøèáêà çàêðûòèÿ õðàíèëèùà', mtError, [mbOK], 0);




end;


Вылетает ошибка AV на строке RepMemo.Lines.add(WS); Не могу понять, в чем дело... вроде типы преобразовал...
Второй вопрос- вот я получил имя контейнера из параметра certkeyinfo^.pwszContainerName.
Как теперь открыть этот контейнер, чтобы получить доступ к публичному и приватному ключам в контейнере?
Еще вопрос -
Если я пытаюсь получить свойство certkeyinfo^.pwszProvName, например так WS:=certkeyinfo^.pwszProvName, то тоже валится ошибка access violation... Тоже не могу понять, почему...
Заранее спасибо за ответ и извините за может быть глупые вопросы...

Отредактировано пользователем 4 марта 2015 г. 10:27:48(UTC)  | Причина: Не указана

Offline dmitrigan  
#5 Оставлено : 4 марта 2015 г. 10:50:29(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
В общем, получилось получить имя контейнера таким способом

Код:

var
P:Pointer;
WS,RT1:AnsiString;

....


 par2:=CERT_KEY_PROV_INFO_PROP_ID;
   cert1:=cert;
      datalen:=0;
       CertGetCertificateContextProperty(cert, par2,nil,datalen) ;
       GetMem(P,datalen);
     CertGetCertificateContextProperty(cert, par2,P,datalen);
     certkeyinfo:=P;
    WS:= certkeyinfo.pwszContainerName;
    RT1:=certkeyinfo.pwszProvName;
    RepMemo.Lines.add(WS);
    RepMemo.lines.Add(RT1);




Вопрос - как мне теперь открыть этот контейнер для использования и доступа к ключевой паре? Заранее спасибо!

Отредактировано пользователем 4 марта 2015 г. 10:51:37(UTC)  | Причина: Не указана

Offline dmitrigan  
#6 Оставлено : 4 марта 2015 г. 12:10:27(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
Разобрался, как открыть - нужно передать имя контейнера в виде SCARD\rutoken_2c4d455c\0A00\04BA, т.е. в том, в котором хранится в структуре типа CRYPT_KEY_PROV_INFO, параметр pwszContainerName.

Offline dmitrigan  
#7 Оставлено : 4 марта 2015 г. 12:49:31(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
Еще вопрос -
пвтаюсь получить версию криптпро -
использую код
Код:

CryptAcquireContext(hProv, nil, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, CRYPT_VERIFYCONTEXT)
    CryptGetProvParam(hProv, 138, nil, cbData,1 );
    GetMem(pbData, cbData);
    CryptGetProvParam(hProv, 138, pbData, cbData,1 )  ;
     ViewMemo.Lines.Add(PAnsiChar(pbData));



Но в мемо либо крякозябры, либо ничего нет. 138-параметр pp_version_ex. пробовал и pp_version - результата нет. Как правильно сделать ? Заранее спасибо.
Offline dmitrigan  
#8 Оставлено : 4 марта 2015 г. 13:46:44(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
Тоже разобрался- возвращает два байта, соответсвенно, типы нужно соответствующие брать. чуть позже код выложу
Offline dmitrigan  
#9 Оставлено : 4 марта 2015 г. 17:10:05(UTC)
dmitrigan

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

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

Сказал(а) «Спасибо»: 6 раз
Ну и вот вопрос. Пытаюсь сделать подпись к файлу. Код использую из статьи http://citforum.oldbank....fense/defense/list6.htm.
Если используется стандандартный криптопровайдер RSA_FULL,то все нормально проходит.
Если же используем криптопровайдер Криптопро CSP, то валится ошибка MessageDlg('Ошибка при определении размера подписи: ' + err, mtError, [mbOK], 0);- BAD algid
Код:

procedure TSigningForm.SignBtnClick(Sender: TObject);
var cont: PChar;
    err: string;
    hProv: HCRYPTPROV;
    key: HCRYPTKEY;
    alg: ALG_ID;
    hash: HCRYPTHASH;
    infile, outfile: file;
    size: DWORD;
    buf: array [0..511] of byte;
    signature: PBYTE;
begin
if not FileExists(DataNameEdit.Text) then
   begin
   MessageDlg('Неверное имя файла!', mtError, [mbOK], 0);
   exit;
   end;
AssignFile(infile, DataNameEdit.Text);
if length(ContainerEdit.Text) = 0
then
    begin
    cont := nil;
    err := 'по умолчанию';
    end
else
    begin
    err := ContainerEdit.Text;
    cont := StrAlloc(length(err) + 1);
    StrPCopy(cont, err);
    end;
if not CryptAcquireContext(hProv, cont, 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75, 0)
then
    begin
    case int64(GetLastError) of
    ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
    ERROR_NOT_ENOUGH_MEMORY: err := 'ERROR_NOT_ENOUGH_MEMORY';
    NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
    NTE_BAD_KEYSET: err := 'NTE_BAD_KEYSET';
    NTE_BAD_KEYSET_PARAM: err := 'NTE_BAD_KEYSET_PARAM';
    NTE_BAD_PROV_TYPE: err := 'NTE_BAD_PROV_TYPE';
    NTE_BAD_SIGNATURE: err := 'NTE_BAD_SIGNATURE';
    NTE_EXISTS: err := 'NTE_EXISTS';
    NTE_KEYSET_ENTRY_BAD: err := 'NTE_KEYSET_ENTRY_BAD';
    NTE_KEYSET_NOT_DEF: err := 'NTE_KEYSET_NOT_DEF';
    NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
    NTE_PROV_DLL_NOT_FOUND: err := 'NTE_PROV_DLL_NOT_FOUND';
    NTE_PROV_TYPE_ENTRY_BAD: err := 'NTE_PROV_TYPE_ENTRY_BAD';
    NTE_PROV_TYPE_NO_MATCH: err := 'NTE_PROV_TYPE_NO_MATCH';
    NTE_PROV_TYPE_NOT_DEF: err := 'NTE_PROV_TYPE_NOT_DEF';
    NTE_PROVIDER_DLL_FAIL: err := 'NTE_PROVIDER_DLL_FAIL';
    NTE_SIGNATURE_FILE_BAD: err := 'NTE_SIGNATURE_FILE_BAD';
    else err := 'Unknown error';
    end;
    MessageDlg('Ошибка открытия контейнера: ' + err, mtError, [mbOK], 0);
    exit;
    end;
case HashRadioGroup.ItemIndex of
0: alg := CALG_MD5;
1: alg := CALG_SHA;
end;
if not CryptCreateHash(hProv, alg, 0, 0, hash) then
   begin
   case int64(GetLastError) of
   ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
   ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
   ERROR_NOT_ENOUGH_MEMORY: err := 'ERROR_NOT_ENOUGH_MEMORY';
   NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
   NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
   NTE_BAD_KEY: err := 'NTE_BAD_KEY';
   NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
   else err := 'Unknown error';
   end;
   MessageDlg('Ошибка создания хеш-объекта: ' + err, mtError, [mbOK], 0);
   exit;
   end;
SaveDialog1.Title := 'Задайте имя файла для хранения подписанных данных';
if SaveDialog1.Execute then
   begin
   AssignFile(outfile, SaveDialog1.FileName);
   rewrite(outfile, 1);
   BlockWrite(outfile, alg, 4);
   reset(infile, 1);
   size := FileSize(infile);
   BlockWrite(outfile, size, 4);
   while not eof(infile) do
         begin
         BlockRead(infile, buf, 512, size);
         BlockWrite(outFile, buf, size);
         if not CryptHashData(hash, @buf, size, 0) then
            begin
            case int64(GetLastError) of
            ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
            ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
            NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
            NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
            NTE_BAD_HASH: err := 'NTE_BAD_HASH';
            NTE_BAD_HASH_STATE: err := 'NTE_BAD_HASH_STATE';
            NTE_BAD_KEY: err := 'NTE_BAD_KEY';
            NTE_BAD_LEN: err := 'NTE_BAD_LEN';
            NTE_BAD_UID: err := 'NTE_BAD_UID';
            NTE_FAIL: err := 'NTE_FAIL';
            NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
            else err := 'Unknown error';
            end;
            MessageDlg('Ошибка при хешировании: ' + err, mtError, [mbOK], 0);
            break;
            end;
         end;
   CloseFile(infile);
   if not CryptSignHash(hash,  AT_KEYEXCHANGE, nil, 0, nil, size) then
      begin
      case int64(GetLastError) of
      ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
      ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
      ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
      NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
      NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
      NTE_BAD_HASH: err := 'NTE_BAD_HASH';
      NTE_BAD_UID: err := 'NTE_BAD_UID';
      NTE_NO_KEY: err := 'NTE_NO_KEY';
      NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
      else err := 'Unknown error';
      end;
      MessageDlg('Ошибка при определении размера подписи: ' + err, mtError, [mbOK], 0);
      CloseFile(outfile);
      exit;
      end;
   GetMem(signature, size);
   if not CryptSignHash(hash, AT_KEYEXCHANGE, nil, 0, signature, size) then
      begin
      case int64(GetLastError) of
      ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
      ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
      ERROR_MORE_DATA: err := 'ERROR_MORE_DATA';
      NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
      NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
      NTE_BAD_HASH: err := 'NTE_BAD_HASH';
      NTE_BAD_UID: err := 'NTE_BAD_UID';
      NTE_NO_KEY: err := 'NTE_NO_KEY';
      NTE_NO_MEMORY: err := 'NTE_NO_MEMORY';
      else err := 'Unknown error';
      end;
      MessageDlg('Ошибка при подписании хеша: ' + err, mtError, [mbOK], 0);
      CloseFile(outfile);
      exit;
      end;
   BlockWrite(outfile, size, 4);
   BlockWrite(outfile, signature^, size);
   CloseFile(outfile);
   end;
if not CryptDestroyHash(hash) then
   begin
   case int64(GetLastError) of
   ERROR_BUSY: err := 'ERROR_BUSY';
   ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
   ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
   NTE_BAD_ALGID: err := 'NTE_BAD_ALGID';
   NTE_BAD_HASH: err := 'NTE_BAD_HASH';
   NTE_BAD_UID: err := 'NTE_BAD_UID';
   else err := 'Unknown error';
   end;
   MessageDlg('Ошибка при уничтожения хеша: ' + err, mtError, [mbOK], 0);
   end;
if not CryptReleaseContext(hProv, 0) then
   begin
   case int64(GetLastError) of
   ERROR_BUSY: err := 'ERROR_BUSY';
   ERROR_INVALID_HANDLE: err := 'ERROR_INVALID_HANDLE';
   ERROR_INVALID_PARAMETER: err := 'ERROR_INVALID_PARAMETER';
   NTE_BAD_FLAGS: err := 'NTE_BAD_FLAGS';
   NTE_BAD_UID: err := 'NTE_BAD_UID';
   else err := 'Unknown error';
   end;
   MessageDlg('Не удалось освободить контекст: ' + err,
       mtError, [mbOK], 0);
   end;
end;

ошибка при выполнении вот этого участка -
Код:
 if not CryptSignHash(hash,  AT_KEYEXCHANGE, nil, 0, nil, size) then

Пробовал и AT_KEYSignature -ошибка таже. В чем может быть проблема?
Offline Kirill Sobolev  
#10 Оставлено : 4 марта 2015 г. 17:23:03(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Ни с одним из
Код:
0: alg := CALG_MD5;
1: alg := CALG_SHA;

'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider' не работает.
Нужен CALG_GR3411(=0x801E=32798), определенный в WinCryptEx.h из SDK.
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Кирилл Соболев за этот пост.
dmitrigan оставлено 14.03.2015(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (2)
3 Страницы123>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.