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

Уведомление

Icon
Error

4 Страницы<1234>
Опции
К последнему сообщению К первому непрочитанному
Offline Рогнар Рыжий  
#11 Оставлено : 17 июня 2019 г. 12:56:08(UTC)
Рогнар Рыжий

Статус: Новичок

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

Сказал(а) «Спасибо»: 5 раз
Автор: Андрей Писарев Перейти к цитате
Автор: Рогнар Рыжий Перейти к цитате

Вы имеете ввиду Wcrypt2.pas


Можно и его.



Можете также подсказать что вы используете для работы с CryptoAPI
Offline Андрей Писарев  
#12 Оставлено : 17 июня 2019 г. 13:04:14(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2035 раз в 1579 постах
Автор: Рогнар Рыжий Перейти к цитате
Автор: Андрей Писарев Перейти к цитате
Автор: Рогнар Рыжий Перейти к цитате

Вы имеете ввиду Wcrypt2.pas


Можно и его.



Можете также подсказать что вы используете для работы с CryptoAPI


jwawincrypt
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
Рогнар Рыжий оставлено 18.06.2019(UTC)
Offline Рогнар Рыжий  
#13 Оставлено : 18 июня 2019 г. 9:55:24(UTC)
Рогнар Рыжий

Статус: Новичок

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

Сказал(а) «Спасибо»: 5 раз
Автор: two_oceans Перейти к цитате
Не не не... это вредный совет, так как этот модуль очень старый, тем более из комплекта дельфи 7, многие функции/константы просто не будут работать, особенно если писать 64-разрядное приложение. Лучше скачать jwawincrypt, например, у меня 1.17 2007/09/05, там хотя бы несложно допилить описание типов хэндлов до 64 битных. Там же есть комментарии на английском к каждой функции, еще можно почитать MSDN игнорируя, что функции по мнению Майкрософт устарели и будут удалены в будущих версиях виндоуз.

Как бы для сертификата даже особо и криптографии не надо, достаточно только нескольких функций. Для получения данных из подписанного файла Вам нужно: 1) выделить нужный текст, содержащий сертификат в Base64 из файла. Это можно сделать либо строковыми функциями либо xml парсерсом и его функциями. Предполагаю, что это Вы уже сделали.

2) декодировать сертификат из Base64, есть огромная куча реализаций для дельфи, но конечно ничто не мешает написать свою. К слову есть и реализация в CryptoAPI StringToBinary, но мне так и не удалось заставить ее работать - вместо декодирования кодирует еще раз, поэтому нашел исходник юнита base64 и скопипастил в свой юнит. Не весь юнит base64 подключил, так как там реализовано в виде объекта и тянулясь длинная объектная цепочка наследования и скомпилированная библиотека распухала в разы.

3) передать сертификат декодированный из base64 certData в
Код:
pCertCont:=CertCreateCertificateContext(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, PByte(CertData.str), CertData.Len);
У меня для удобства передачи между библиотеками свои строки - запись в которой str адрес буфера строки, Limit длина буфера выделенная, Len занятая длина буфера без конечного символа 0. Возвращается указатель на контекст сертификата, контекст удобен тем, данные закодированные в сертификате автоматически частично раскодированы и их можно уже и вручную выдергивать, но мы же не варвары, есть специальные функции для имени и различных хэшей сертификата.

С другой стороны, вручную удобнее выдергивать серийный номер сертификата, так как в дельфи его надо заодно перевернуть. Перевод номера сертификата в десятичное представление - отдельная тема, так как у стандартных целочисленных типов не хватает длины чтобы вместить скажем 22 или 27 байт серийного номера.

В коде выше конечно отличная альтернатива шагам 4 и 5.


Спасибо вроде получилось, я была в отчаянии, вы меня спасли когда сделаю покрасивее скину сюда вдруг кому пригодится

Offline Рогнар Рыжий  
#14 Оставлено : 18 июня 2019 г. 10:20:30(UTC)
Рогнар Рыжий

Статус: Новичок

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

Сказал(а) «Спасибо»: 5 раз
Автор: two_oceans Перейти к цитате

rData:=CertGetNameString(pCertCont, strDisp, StrTp, pTpPara, @(Rez.str^), Rez.Limit);[/code]Можно регулировать представление через strDisp самое

я эту строчку не поняла и сделала так, можете поподробнее объяснить rData какого типа и как можно значение сразу в строковую переменную записать?
Код:
var
  CertName: array[0..255] of Char;
begin
  MTable1.Open;
  if CertGetNameString(pCertCont, CERT_NAME_ATTR_TYPE, 0, PAnsiChar('2.5.4.4'),
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  showmessage( CertName);
  MTable1.Edit;
  MTable1.Append;
  MTable1.FieldByName('fam').AsString:=CertName;
  if CertGetNameString(pCertCont, CERT_NAME_ATTR_TYPE, 0, PAnsiChar( '2.5.4.42'),
    CertName, 256) = 0 then
    RaiseLastWin32Error;
  showmessage( CertName);
  MTable1.FieldByName('imot').AsString:=CertName;
  MTable1.Post;
end;

Отредактировано пользователем 18 июня 2019 г. 10:22:48(UTC)  | Причина: Не указана

Offline two_oceans  
#15 Оставлено : 18 июня 2019 г. 11:45:05(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Автор: Рогнар Рыжий Перейти к цитате
Автор: two_oceans Перейти к цитате

Код:
rData:=CertGetNameString(pCertCont, strDisp, StrTp, pTpPara, @(Rez.str^), Rez.Limit);
Можно регулировать представление через strDisp самое

я эту строчку не поняла и сделала так, можете поподробнее объяснить rData какого типа и как можно значение сразу в строковую переменную записать?
Почти правильно сделали - в таком виде Вы не узнаете какая на самом деле длина возвращается в CertName вместо фамилии из 10 символов скопируте все 256 символов. Если строка неинициализирована, то много мусора скопируется. Мелочь конечно, но по вашему коду Вы получается выдаете исключение на сертификаты без ФИО, наряду с ошибками CryptoAPI. rData это как раз та самая длина возвращенного текста, тип 32-битное беззнаковое целое число, у меня дельфисовместимый компилятор, этот тип называется dword или cardinal или ulong.

В обычную строковую записать может быть проблемой, так как по умолчанию string синоним ansistring или longstring, а у них адрес буфера прыгает при любом изменении, что неприемлемо при передаче в WinApi вообще и в CryptoApi в частности. Если длины 255 достаточно, то можно использовать shortstring (там байт длины и фиксированный буфер длиной 255 символов). При этом в пятый параметр передается ссылка на первый символ @s[1] а после вызова нужно не забыть записать s[0]:=chr(rdata and $ff); Если не достаточно 255 байт, то можно попробовать обойтись PChar PAnsiChar PWideChar, там с длиной манипуляций не нужно, но может быть проблема в сложных типах когда Си (на котором пишут в Майкрософт) трактует поле как однозначно указатель (а бывает как указатель на указатель на указатель на данные), а Дельфи то как указатель, то как строку. Все это и сподвигло меня перейти на самописный тип-запись для хранения строк, мороки не то чтобы стало больше, зато точно знаю поведение. Плохо совместимо кодом для ansistring, но так как этот код в основном объекты, а объекты несовместимо перетаскивать между библиотеками, решил что для библиотек самописный тип-запись самое то.

В продолжение вчерашнего вопроса о разных модулях - какой тип указывается в объявлении функции зависит от используемого модуля. У Вас похоже пятый параметр объявлен как var. На дельфи это конечно удобнее, но декларации winapi позволяют в подобные строковые параметры передать nil вместо адреса буфера для запроса длины нужного буфера, а var переменная дельфи не может быть nil, то есть более корректно объявить параметр как указатель или P****Char для всей полноты функционала. У меня модуль с объявлениями как указателями, но строгий тип указателя на буфер не соответствует строгому типу указателя в объявлении PByte или PChar, поэтому в строке-примере сами данные ^ от указателя и снова беру адрес @, тип становится нетипизированным указателем совместимым с любым указателем, это конечно равносильно явному приведению типа, но на приведение мой компилятор выдает notice, а комбинацию разименовывания указателя с взятием адреса считает допустимой.

Отредактировано пользователем 18 июня 2019 г. 12:18:17(UTC)  | Причина: Не указана

Offline Рогнар Рыжий  
#16 Оставлено : 27 июня 2019 г. 10:37:32(UTC)
Рогнар Рыжий

Статус: Новичок

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

Сказал(а) «Спасибо»: 5 раз
Возник еще вопрос не могу найти информацию как достать дату начала и дату окончания сертификата

Offline two_oceans  
#17 Оставлено : 27 июня 2019 г. 11:05:07(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Не находится наверно потому что слишком просто. Смотрим структуру CERT_INFO: https://technet.microsof...r/aa377200%28v=vs.110%29
Находим там даты (NotBefore NotAfter палятся просто по типу данных), находим указатель на структуру в контексте сертификата (вроде как есть и специальная функция для получения CERT_INFO, но тут как раз можно "срезать путь" прямым обращением к памяти). Пусть pCertCont это контекст сертификата, тогда получаем что-то вроде (точное написание может отличаться в зависимости от модуля, смотря как модуль назвал поля в записях):
Код:
var DtStart,DtEnd:TFILETIME;

DtStart:=pCertCont^.pCertInfo^.NotBefore;
DtEnd:=pCertCont^.pCertInfo^.NotAfter;
Дальше из TFILETIME переводите в нужный формат. И мне конечно любопытно правда ли Вы будете использовать дату начала?

Если же интересна информация о сроке действия закрытого ключа, то там посложнее.

Отредактировано пользователем 27 июня 2019 г. 11:12:31(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
Рогнар Рыжий оставлено 27.06.2019(UTC)
Offline Рогнар Рыжий  
#18 Оставлено : 27 июня 2019 г. 11:11:17(UTC)
Рогнар Рыжий

Статус: Новичок

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

Сказал(а) «Спасибо»: 5 раз
Автор: two_oceans Перейти к цитате
Смотрим CERT_INFO: https://technet.microsof...r/aa377200%28v=vs.110%29
Находим там даты, находим указатель на структуру в контексте сертификата. Пусть pCertCont это контекст сертификата, тогда получаем что-то вроде (точное написание может отличаться в зависимости от модуля):
Код:
var DtStart,DtEnd:TFILETIME;

DtStart:=pCertCont^.pCertInfo^.NotBefore;
DtEnd:=pCertCont^.pCertInfo^.NotAfter;
Дальше из TFILETIME переводите в нужный формат.


Ошибку выдает

Incompatible types: 'Windows._FILETIME' and 'JwaWinType._FILETIME'

Offline two_oceans  
#19 Оставлено : 27 июня 2019 г. 11:14:38(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Поэтому я и выкидываю модуль Windows где могу. И та версия и другая импортированы из одного заголовочного файла Си, но Дельфи их считает разными. Нужно явное приведение типа:
Код:
DtStart:=Windows._FILETIME(pCertCont^.pCertInfo^.NotBefore);
DtEnd:=Windows._FILETIME(pCertCont^.pCertInfo^.NotAfter);

Отредактировано пользователем 27 июня 2019 г. 11:15:59(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
Рогнар Рыжий оставлено 27.06.2019(UTC)
Offline Infopol  
#20 Оставлено : 3 июня 2023 г. 15:11:44(UTC)
Infopol

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

Группы: Участники
Зарегистрирован: 21.03.2022(UTC)
Сообщений: 33
Откуда: Краснодарский край

Сказал(а) «Спасибо»: 17 раз
CheckGetSpecification.xml.xmlresponse.xml (7kb) загружен 2 раз(а).Пытался реализовать пример с использованием JwaWinCrypt тоже ничего не получилось.
Нужно из сертификата X509 вытащить название клиента,ИНН,КПП.
Хотим сделать свой документооборот - Создается XML файл УПД ,подписываетсяи отправляется клиенту.
Клиент проверяет подпись и проверяет соответствие ИНН и КПП и далее загружается документ в программу
Код:

procedure TForm1.Button1Click(Sender: TObject);
var
  i, n: Integer;
   M: TMemoryStream;
  BPos, EPos: Integer;
  Name,Value: String;
  SL: TStringList;
  pc:PCERT_INFO ;
  pb:PByte;
   encType: DWORD;
  PS: Pbyte;
  sz: DWORD;
  skip: DWORD;
  flags: DWORD;
 // I: Integer;
 pCert:PCCERT_CONTEXT;
begin
 SL := TStringList.Create;
   M := TMemoryStream.Create;
 if OpenDialog1.Execute then
 SL.LoadFromFile(OpenDialog1.FileName);
  Memo1.Clear;
 BPos := Pos('<'+Edit1.Text+'X509Certificate>', SL.Text) + Length('<'+Edit1.Text+'X509Certificate>');
 EPos := Pos('</'+Edit1.Text+'X509Certificate>', SL.Text);

 Value := ToBase64( Copy(SL.Text, BPos, EPos - BPos));
//Value:=IdEncoderMIME1.EncodeString(Value);
 Memo1.Lines.Add(Value);
 //CertCreateCertificateContext(        https://www.cyberforum.ru/delphi/thread302892.html
 {CertCreateCertificateContext(X509_ASN_ENCODING or
PKCS_7_ASN_ENCODING, M.Memory, M.Size);}
  label1.Caption:=IntToStr(Length(Value)) ;
          // dwSize := CertGetName////(CERT_CONTEXT, dwType, dwFlags, pvTypePara, nil, 0);
  //  Win32Check(dwSize <> 0);

  pCert:= CertCreateCertificateContext(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, PByte(Value),Length(Value) );
  //  CertGetNameStringA(pCert, dwType, dwFlags, pvTypePara, nil, 0)

  //  IntToStr(pCert.cbCertEncoded);
//pc:=pCert^.pCertInfo;
  //Memo1.Lines.Add(pCertCont^);
 //   pCert^.pCertInfo^.NotBefore ;
//pcert^.pCertInfo^.NotAfter      ;
//Pb:=pcert^.pCertInfo^.Issuer.pbData   ;
//pcert^.pCertInfo^.Issuer        ;
//pcert^.pCertInfo^.Subject       ;
//pcert^.pCertInfo^.SerialNumber   ;

         try
     //    Byte
   // pc:= pCert.pCertInfo ;
//   pCert.pCertInfo.Issuer;
    //    (GetSerialNumber(pCert));
//    DecodeSerialNumber(pCert.pCertInfo.SerialNumber) ;

    finally
  if Assigned(pCert) then
 try
  ShowMessage(GetSerialNumber(pCert)) ;

 finally
 if not CertFreeCertificateContext(pCert) then
ShowMessage(SysErrorMessage(GetLastError)) ;
      end
      else

      SL.Text:= Value;
      //M.;

      flags := CRYPT_STRING_BASE64REQUESTHEADER;
      //CryptStri
     // CryptStringToBinary(
     //https://delphisources.ru/forum/showthread.php?t=27645
       //  M.Write(SL.)
               // M.LoadFromStream(SL.);
 //     CryptStringToBinary(PChar(SL.Text), Length(SL.Text), flags, nil, sz, skip, flags);
        // ShowMessage(PS.);
        GetMem(PS, sz);
 //       Pchar(sz);
 //PS:=PByte(SL.Text);

                try
               //   CryptStringToBinary(PChar(SL.Text), Length(SL.Text), flags, Pointer(PS), sz, skip, flags);
          pCert := CertCreateCertificateContext({encType}X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, PS, sz);
        finally
          FreeMem(PS);
        end;
          if Assigned(pCert) then
          ShowMessage(GetSerialNumber(pCert));
     {LOG(FormatDateTime('Äåéñòâèòåëåí ñ: dd.mm.yyyy',
            FileTime2DateTime(cert^.pCertInfo^.NotBefore)));
          LOG(FormatDateTime('Äåéñòâèòåëåí äî: dd.mm.yyyy',
            FileTime2DateTime(cert^.pCertInfo^.NotAfter)));
          LOG('Ñóáúåêò: ' + DecodeName(cert^.pCertInfo^.Subject));
          LOG('Ïîñòàâùèê: ' + DecodeName(cert^.pCertInfo^.Issuer));
          LOG('******');
          LOG('Ïàðñèì ìûëî ñóáúåêòà: ' + GetValue('',
            DecodeName(cert^.pCertInfo^.Subject), 'E=', ',', I));
          LOG('******');
          LOG('Ñåðèéíûé íîìåð: ' + DecodeSerialNumber
            (cert^.pCertInfo^.SerialNumber));}

      // M.Read()

end;
   //  CertFreeCertificateContext( CertInfo)      ;
  //   ByteArrayToStr(CertInfo.pCertInfo.SerialNumber.pbData,CertInfo.pCertInfo.SerialNumber.cbData);

   //  GetSerialNumber(pCert)  ;
 SL.Free;
 M.Free;
end;

Отредактировано пользователем 3 июня 2023 г. 15:30:10(UTC)  | Причина: Не указана

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