Статус: Новичок
Группы: Участники
Зарегистрирован: 26.07.2018(UTC) Сообщений: 4
|
Добрый день! Подписываю документ содержащий кириллицу (формат подписи XMLDsig). При проверке подписанного файла сервисом - "Подпись не действительна". Если всю кириллицу заменить на латинские буквы - "Подпись действительна". Алгоритмы ключа: ГОСТ Р 34.10-2001 DH, ГОСТ Р 34.10-2001, ГОСТ Р 34.11-94, ГОСТ 28147-89. Подскажите, что я делаю не так и где искать проблему?
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 26.07.2018(UTC) Сообщений: 4
|
PS. Подписываю SOAP-пакет из Delphi 10 Seattle компонентами Clever Internet Suite.
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 26.07.2018(UTC) Сообщений: 4
|
Разобрался! Проблема была при передаче подписанного файла из clSoapMessage в файл или на передачу: надо было заменить clSoapMessage.RequestSource (TStrings) на clSoapMessage.RequestStream (TStream). Вообще не используйте TStrings и его производные при работе сертификатами! В моём случае кодировка после подписания изменялась на windows-1251. Мой рабочий код для каноникализации и подписания XML форматом подписи XMLDsig с использованием компонентов Clever Internet Suite v9.1 (я работаю поверх Indy THTTPRIO, т.е. получаю сгенерированный файл, подписываю его и отправляю. Можно было бы всё сделать с помощью TclSoapMessage, но мне некогда с ним разбираться):
Код:type
TForm1 = class(TForm)
private
FSoapMessage: TclSoapMessage;
FclCertificateStore: TclCertificateStore;
procedure GetSigningCertificate(Sender: TObject;
AKeyInfo: TclXmlKeyInfo; var ACertificate: TclCertificate;
AExtraCerts: TclCertificateList; var Handled: Boolean);
procedure PrepareSoapMessage;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FclCertificateStore := TclCertificateStore.Create(Self);
FclCertificateStore.ProviderType := 75;
FclCertificateStore.Open('MY', TclCertificateStoreLocation.slCurrentUser);
FSoapMessage := TclSoapMessage.Create(Self);
FSoapMessage.OnGetSigningCertificate := GetSigningCertificate;
FSoapMessage.SecurityConfig.ProviderType := 75;
FSoapMessage.SecurityConfig.HashAlgorithms.Clear;
with FSoapMessage.SecurityConfig.HashAlgorithms.Add do
begin
Identifier := 32798;
Name := 'gostr3411';
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(FSoapMessage);
FreeAndNil(FclCertificateStore);
end;
procedure TForm1.GetSigningCertificate(Sender: TObject;
AKeyInfo: TclXmlKeyInfo; var ACertificate: TclCertificate;
AExtraCerts: TclCertificateList; var Handled: Boolean);
begin
//этот код рассчитан, что в системе будет один сертификат и он окажется нужным
ACertificate := FclCertificateStore.Items[0];
end;
procedure TForm1.PrepareSoapMessage;
begin
FSoapMessage.BodyID := 'msgBody';
with FSoapMessage.Signatures.Add do
begin
SignatureMethod := 'http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411';
with References.Add do
begin
DigestMethod := 'http://www.w3.org/2001/04/xmldsig-more#gostr3411';
URI := '#msgBody';
end;
with References.Add do
begin
DigestMethod := 'http://www.w3.org/2001/04/xmldsig-more#gostr3411';
URI := '#msgTimestamp';
end;
end;
//дату создания подписи хотят видеть по Гринвичу и в таком формате, МСК = +3 отсюда и -3
with FSoapMessage.Timestamp do
begin
Created := FormatDateTime('yyyy-mm-dd', Now) + 'T' + FormatDateTime('hh:mm:ss.zzz', IncHour(Now, -3)) + 'Z';
Expires := FormatDateTime('yyyy-mm-dd', Now) + 'T' + FormatDateTime('hh:mm:ss.zzz', IncHour(IncMinute(Now, 10), -3)) + 'Z';
ID := 'msgTimestamp';
end;
end;
procedure TForm1.HTTPRioBeforeExecute(const MethodName: string; SOAPRequest: TStream);
var
S: TStringStream;
begin
S := TStringStream.Create;
try
S.LoadFromStream(SOAPRequest);
FSoapMessage.BuildSoapMessage(S.DataString);
finally
FreeAndNil(S);
end;
//подготовка компонента к подписи
//надо выполнять после вызова BuildSoapMessage!!!
PrepareSoapMessage();
//подписываем XML
FSoapMessage.Sign();
//пишем подписанный XML в поток отправки
FSoapMessage.RequestStream.Seek(0, soFromBeginning);
SOAPRequest.Seek(0, soFromBeginning);
SOAPRequest.CopyFrom(FSoapMessage.RequestStream, FSoapMessage.RequestStream.Size);
//логируем отправляемое сообщение
{TODO: здесь можно сохранить подписанный отправляемый файл}
SOAPRequest.Seek(0, soFromBeginning);
end;
procedure TForm1.HTTPRioAfterExecute(const MethodName: string; SOAPResponse: TStream);
begin
{TODO: здесь можно сохранить ответ}
end;
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 26.07.2018(UTC) Сообщений: 4
|
Забыл сказать. Пришлось немного модифицировать код компонентов, иначе не срабатывало подписание документа. В юните clSoapSecurity произвести следующие изменения:
function TclXmlSignatureRSA.SupportsMethod(const ASignatureMethod: string): Boolean; begin Result := (System.Pos('rsa', ASignatureMethod) > 0) or (System.Pos('gostr34102001', ASignatureMethod) > 0); end;
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close