powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Электронный больничный ЭЛН
25 сообщений из 196, страница 4 из 8
Электронный больничный ЭЛН
    #39742227
maratvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shuraken,

Видимо вы пропустили первый шаг: TlbExp.exe
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39742350
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratvg,

Нет, не забыл, там тоже ошибка
TlbExp : error TX0000 : Невозможно загрузить файл или сборку "file:///C:\FSSRF\A
RM_FSS\gostcryptography.dll" или один из зависимых от них компонентов. Сборка со
здана в более поздней версии среды выполнения чем текущая, и не может быть загру
жена.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39742428
maratvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shuraken,

Нужно версию SDK более свежую

D:\GostCryptography>ft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\TlbExp.exe" D:\GostCryptography\GostCryptography.dll
Microsoft (R) .NET Framework Assembly to Type Library Converter 4.6.1055.0
Copyright (C) Microsoft Corporation. All rights reserved.

Assembly exported to 'D:\GostCryptography\GostCryptography.tlb'

D:\GostCryptography>rogram Files\Microsoft SDKs\Windows\v7.1\Bin\TlbExp.exe" D:\GostCryptography\GostCryptography.dll
Microsoft (R) .NET Framework Assembly to Type Library Converter 3.5.30729.1
Copyright (C) Microsoft Corporation. All rights reserved.

TlbExp : error TX0000 : Невозможно загрузить файл или сборку "file:///D:\GostCryptography\GostCryptography.dll" или один
из зависимых от них компонентов. Сборка создана в более поздней версии среды выполнения чем текущая, и не может быть за
гружена.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39742450
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratvg,

Огромное спасибо, установил.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39742518
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratvg,

правда, там описание функционала отличается от того, что написали Вы. Можете объяснить назначение pSenderCertName (function encryptMsg(const pProvName: WideString; const pCertName: WideString;
const pSenderCertName: WideString; const pSOAPMsg: WideString): WideString;)?
На всякий случай прилагаю архив с моим сгенерированным pas-файлом.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39742751
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С этим разобрался - взял GostCryptography из папки FssTools, а не ARM_FSS. Правда, теперь там другая проблема: сообщение "Операция не может быть выполнена с текущим ключом", после чего слетают все настройки хранилища сертификатов и приходится перезагружать компьютер. Так что всё весело.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39742854
maratvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shuraken,

Работал только со старой длл-кой, сейчас нет надобности, поэтому что там поменялось не слежу.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39743077
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShurakenС этим разобрался - взял GostCryptography из папки FssTools, а не ARM_FSS. Правда, теперь там другая проблема: сообщение "Операция не может быть выполнена с текущим ключом", после чего слетают все настройки хранилища сертификатов и приходится перезагружать компьютер. Так что всё весело.

Через CSP контейнер (по сертификату) тестируется без проблем?
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39743277
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sql2012,

в смысле, нормально ли подписывается и принимается ФСС? Да, там всё нормально, но реализовано не через GostCryptography.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39749662
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Очередные грабли с ЭЛН по ФСС. На сей раз шифрование.
Подписанные запросы на получение и отправку данных без проблем обрабатываются тестовым сервером ФСС. Работаю над шифрованием. Вот с ним и возникла проблема.
За основу взял готовый код tkolomiets Электронный больничный ЭЛН . Допилил его под Делфи 7, на которой работаю и стал пробовать шифровать и отсылать на тестовый сервер ФСС. В результате всё время возникает ошибка

ru.ibs.cryptoprto.jcp.wrapper.eln.ws.client.generated.CryptoException_Exception: Не удалось расшифровать сообщение. Возможно сообщение зашифровано на ключе отличном от ключа уполномоченного лица ФСС. Проверьте правильность и актуальность ключа уполномоченного лица ФСС.

С сертификатами всё в порядке, с криптопровайдером тоже. В чём ошибка, понять не могу. В аттаче образец подписанного сообщения, зашифрованного и код. Буду признателен, если посмотрите и укажете на проблему.

С уважением, Александр.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750452
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кто может подсказать аналоги следующих функций для Делфи 7?

TNetEncoding.Base64.EncodeBytesToString
TEncoding.Ansi.GetString
TNetEncoding.Base64.DecodeStringToBytes
TEncoding.Default.GetBytes

А то наткнулся на них в аттаче по подписанию и шифрованию ЭЛН, и не уверен, что правильно подобрал аналоги.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750455
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shuraken,
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750472
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Во-первых, это плохой юнит, уже разбирали.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure Base64Encode(const InBuffer; InSize: Cardinal; var OutBuffer); register; overload;
var
  ByThrees, LeftOver: Cardinal;
asm
  mov ESI, [EAX]
  mov EDI, [ECX]
  mov EAX, EBX // <<-- что за значение тут в EBX ?..
  mov ECX, $03
  xor EDX, EDX
  div ECX
  mov ByThrees, EAX 
  ...



Во-вторых, в дельфи есть родной: 2009-XE - EncdDecd.pas, XE2+ - Soap.EncdDecd.pas и ещё вот это .

В-третьих, если родной не нравится можно из какого-нибудь synops'а взять.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750531
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvprgreat,

во-вторых, в дельфи есть родной: 2009-XE - EncdDecd.pas, XE2+ - Soap.EncdDecd.pas и ещё вот это .

В-третьих, если родной не нравится можно из какого-нибудь synops'а взять.

Я говорил о Делфи 7. В нём да, есть encddecd, и честно говоря, не совсем понял, как соотнести его
procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(Input, Output: TStream);
function EncodeString(const Input: string): string;
function DecodeString(const Input: string): string;

с тем, что я написал

TNetEncoding.Base64.EncodeBytesToString
TEncoding.Ansi.GetString
TNetEncoding.Base64.DecodeStringToBytes
TEncoding.Default.GetBytes
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750666
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShurakenЯ говорил о Делфи 7. В нём да, есть encddecd, и честно говоря, не совсем понял, как соотнести его

TNetEncoding.Base64.EncodeBytesToString
TEncoding.Ansi.GetString
TNetEncoding.Base64.DecodeStringToBytes
TEncoding.Default.GetBytes

Base64:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
uses
  EncdDecd;

const
  Data = 'PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c3RyaW5nPtiq2LPYqjwvc3RyaW5nPg==';

var
  bin: string;

begin
  bin := DecodeString(Data); //  в bin - двоичные данные
  ...


А вот вместо TEncoding, скорее всего, придётся писать свою обёртку над MultiByteToWideChar и WideCharToMultiByte .
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750669
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpА вот вместо TEncoding, скорее всего, придётся писать свою обёртку над MultiByteToWideChar и WideCharToMultiByte .
Ну или так (не проверял):
Код: pascal
1.
2.
3.
4.
5.
6.
7.
var
  ansi: string;
  def: widestring;
begin
  ansi := 'это кодировка винды (обычно 1251)';
  def := widestring(ansi); // в def теперь unicode
  ...
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750720
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обертки, что бы долго не мучатся (взяты из JCL):

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
function StringToWideStringEx(const S: ansistring; CodePage: word): WideString;
var
 InputLength, OutputLength: NativeInt;
begin
 InputLength  := Length(S);
 OutputLength := MultiByteToWideChar(CodePage, 0, PAnsiChar(S), InputLength, nil, 0);
 SetLength(Result, OutputLength);
 MultiByteToWideChar(CodePage, 0, PAnsiChar(S), InputLength, PWideChar(Result), OutputLength);
end;

function WideStringToStringEx(const WS: WideString; CodePage: word): ansistring;
var
 InputLength, OutputLength: NativeInt;
begin
 InputLength  := Length(WS);
 OutputLength := WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, nil, 0, nil, nil);
 SetLength(Result, OutputLength);
 WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, PAnsiChar(Result), OutputLength, nil, nil);
end;
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39750809
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpА вот вместо TEncoding, скорее всего, придётся писать свою обёртку над MultiByteToWideChar и WideCharToMultiByte .

А функции из этого файла подойдут?
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39752089
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Друзья, прошу помощи с расшифровкой.
Мне удалось отправить сообщение в ФСС и получить зашифрованный ответ. Теперь бьюсь над расшифровкой. Сначала попробовал сделать через GostCryptography.dll, указывая тип провайдера из сертификата, которым подписывал сообщение
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
procedure TEncodeDecodeFSS(ProvCSP: string; EncryptMessage: string);
begin
    GostSoap := TGostDecryptSOAP.Create(Self);
    try
      GostSoap.Connect;
      try
          mSignature.Lines.Text := GostSoap.decryptMsg(ProvCSP, EncryptMessage);
      finally
        GostSoap.Disconnect;
      end;
    finally
      FreeAndNil(GostSoap);
    end;
end;


получаю ошибку "Данные шифра не указаны".

Попробовал по другому, застрял на ошибке "Плохие данные":

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    CheckCryptoCall(CryptGetUserKey(ACryptoProvider, AT_KEYEXCHANGE, @hPrivateKey));
//    CheckCryptoCall(CryptAcquireCertificatePrivateKey(rec^.Cert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, nil, @hPrivateKey, @keySpec, @callerFree));

    // Формирование BLOB-ов публичного и сессионного ключей ФСС на основе зашифрованного ключа из ответа ФСС
    GetResponseKeysBlobs(ASOAPResponse, remotePublicKeyBlob, remoteSessionKeyBlob);

    // Получение ключа согласования импортом открытого ключа ФСС (отправителя)
    // на локальном закрытом ключе (получателя).
    // ошибка происходит здесь
    CheckCryptoCall(CryptImportKey(ACryptoProvider, @remotePublicKeyBlob[0], Length(remotePublicKeyBlob), hPrivateKey, 0, @hAgreeKey));


при этом подозреваю, что ошибку допустил где-то здесь:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
procedure TfrmSignatureFromCertificate.GetResponseKeysBlobs(
  ASOAPResponse: IXMLDocument; out APublicKeyBlob,
  ASessionKeyBlob: TByteArray);

const OpenPublicKeyBlob: array[0..35] of byte =
      ($06,       // bType = PUBLICKEYBLOB
       $20,       // bVersion = 0x20
       $00, $00,
       $23, $2E, $00, $00, // KeyAlg = ALG_SID_GR3410EL
       $4D, $41, $47, $31, //Magic = GR3410_1_MAGIC
       $00, $02, $00, $00, // BitLen = 512
       // bASN1GostR3410_94_PublicKeyParameters
       $30, $12,
       $06, $07 ,
       $2A, $85, $03, $02, $02, $24, $00,
       $06, $07,
       $2A, $85, $03, $02, $02, $1E, $01);

  trBlob:  array[1..71] of byte =
  ($01, $20, $00, $00, $1E, $66, $00, $00,
   $FD, $51, $4A, $37, $1E, $66, $00, $00,
   $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, // ключ
   $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
   $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
   $30, $09, $06, $07,
   $2A, $85, $03, $02, $02, $1F, $01); // UKM (157,8)
var
  i: integer;
  transportNode: IXMLNode;
  transport, publicKey, sessionKey,
  sessionSV, sessionMAC: TByteArray;
  trText: string;
  enc: TUTF8Encoding;
begin
  try
    transportNode := ASOAPResponse.DocumentElement
                     .ChildNodes[1]  // Body
                     .ChildNodes[0]  // EncryptedData
                     .ChildNodes[1]  // KeyInfo
                     .ChildNodes[0]  // EncryptedKey
                     .ChildNodes[2]  // CipherData
                     .ChildNodes[0]; // CipherValue

 //изначальный код
{    transport := TNetEncoding.Base64.DecodeStringToBytes(transportNode.Text);}
//мои переделки под Delphi7
    enc := TUTF8Encoding.Create;
    try
      transport := TByteArray(enc.GetBytes(transportNode.Text));
      trText := Q_Base64Decode(enc.GetString(TBytes(transport)));
    finally
      FreeAndNil(enc);
    end;
    SetLength(transport, length(trText));
    system.Move(Windows.PByte(trText)^, Pointer(transport)^, length(trText));

    publicKey := Copy(transport, 93, 64);
    sessionKey := Copy(transport, 7, 32);
    sessionMAC := Copy(transport, 41, 4);
    sessionSV := Copy(transport, 159, 8);

//изначальный код
{    APublicKeyBlob := 
      [
       $06,       // bType = PUBLICKEYBLOB
       $20,       // bVersion = 0x20
       $00, $00,
       $23, $2E, $00, $00, // KeyAlg = ALG_SID_GR3410EL
       $4D, $41, $47, $31, //Magic = GR3410_1_MAGIC
       $00, $02, $00, $00, // BitLen = 512
       // bASN1GostR3410_94_PublicKeyParameters
       $30, $12,
       $06, $07 ,
       $2A, $85, $03, $02, $02, $24, $00,
       $06, $07,
       $2A, $85, $03, $02, $02, $1E, $01
      ] + publicKey;



    // сборка SessionKey BLOB из статической части и параметров сессионного ключа
    ASessionKeyBlob :=
    [
     $01, // bType = SIMPLEBLOB
     $20, // bVersion = 0x20
     $00,$00 ,
     $1E,$66 ,$00 ,$00, // KeyAlg = CALG_G28147
     $FD,$51 ,$4A ,$37, // Magic = G28147_MAGIC
     $1E,$66 ,$00 ,$00] // EncryptKeyAlgId = CALG_G28147
     + sessionSV + sessionKey + sessionMAC +
    [// ASN.1 Sequence + OID Header
       $30 ,$09 ,$06 ,$07,
     // OID_GOST_R28147_89_CryptoPro_A_ParamSet 1.2.643.2.2.31.1
     $2A ,$85 ,$03 ,$02 ,$02 ,$1F ,$01
    ];   }
//мои переделки под Delphi7
    SetLength(APublicKeyBlob, 100);
    for i := 0 to 35 do
      APublicKeyBlob[i] := OpenPublicKeyBlob[i];
    for i := 1 to 64 do
      APublicKeyBlob[i + 35] := publicKey[i];
    setLength(ASessionKeyBlob, 134);
    for i := 1 to 71 do
      ASessionKeyBlob[i] := trBlob[i];
    for i := 1 to 8 do
      ASessionKeyBlob[i+16] := sessionSV[i];
    for i := 1 to 32 do
      ASessionKeyBlob[i+24] := sessionKey[i];
    for i := 1 to 4 do
      ASessionKeyBlob[i+56] := sessionMAC[i];
  finally
    SetLength(sessionSV, 0);
    SetLength(sessionMac, 0);
    SetLength(sessionKey, 0);
    SetLength(publicKey, 0);
    SetLength(transport, 0);
  end;
end;



У кого стоит Embarcadero, проверьте пожалуйста, какой результат возвращает функция TNetEncoding.Base64.DecodeStringToBytes(transportNode.Text);
Если ей на вход поступает вот такое значение (CipherValue):
MIGkMCgEINMuXESbgvBOY8udqVlHxbfpPgcKAS5Ew6HTwpGhz269BASOb6SYoHgGByqFAwICHwGgYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARAZMGkZ+ODNscutZgYgesDlGkN5AiubvNOhdJOaIZK+QRoVkMZnq22foPv660Khhs9zj5BTwx5u1HOITYmgEj1fwQIkfNcLhh/iDk=

С уважением, Александр.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39752466
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratvgв GostCryptography_TLB.pas будут созданы классы TGostEncryptSOAP, TGostDecryptSOAP, которые собственно и использовались.
для примера
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function EncryptSOAP(const ASignedXml: WideString; const ACertName: string): WideString;
var
  GostEncryptSOAP: TGostEncryptSOAP;
begin
  GostEncryptSOAP := TGostEncryptSOAP.Create(nil);
  try
    GostEncryptSOAP.Connect;
    Result := GostEncryptSOAP.encryptMsg(CP_GR3410_2001_PROV_A, ACertName, ASignedXml);
  finally
    GostEncryptSOAP.Free;
  end;
end;



Если несложно, приведите пожалуйста, пример расшифровки. Для шифрования Ваш код подошёл, но пока не могу понять, как расшифровывать. Делаю так, подставляя разные параметры в decryptMsg, но каждый раз выходит одна и та же ошибка "Данные шифра не указаны".
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
    GostSoap := TGostDecryptSOAP.Create(Self);
    try
      GostSoap.Connect;
      try
        soapRequestDoc := LoadXMLDocument('FSSEncryptXML.xml');
        try
          decryptMessage := GostSoap.decryptMsg(CP_GR3410_2001_PROV_A, soapRequestDoc.DocumentElement.XML);
        finally
          SoapRequestDoc := nil;
        end;
      finally
        GostSoap.Disconnect;
      end;
    finally
      FreeAndNil(GostSoap);
    end;
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39752574
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ура, удалось разобраться с GostDecryptSOAP. Оказывается, ему надо было "скармливать" не всё сообщение, а лишь EncryptedData с содержимым. Но тут возникла другая проблема. Ошибка исчезла, но расшифровка не происходит. Подаёшь на вход зашифрованное сообщение, и его же получаешь на выходе.
Что самое интересное, вот такой код показывает, что обе функции работают нормально. Подаю на вход подписанный xml, указываю свой сертификат и вижу зашифрованное сообщение, после чего расшифровываю его и вижу исходное сообщение.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
  EncSoap := TGostEncryptSOAP.Create(Self);
  try
    EncSoap.Connect;
    try
      EncryptedResponse := EncSoap.encryptMsg(CP_GR3410_2001_PROV_A, CertName, SignedXML);
      mEncryptedResponse.Text := EncryptedResponse;
    finally
      EncSoap.Disconnect;
    end;
  finally
    FreeAndNil(EncSoap);
  end;

  DecSoap := TGostDecryptSOAP.Create(Self);
  try
    DecSoap.Connect;
    try
      DecryptedResponse := DecSoap.decryptMsg(CP_GR3410_2001_PROV_A, EncryptedResponse);
      mDecryptedResponse.Text := DecryptedResponse;
    finally
      DecSoap.Disconnect;
    end;
  finally
    FreeAndNil(DecSoap);
  end;


А вот зашифровав сообщение сертификатом ФСС, ничем расшифровать его не могу. Кто-нибудь может объяснить, с чем это может быть связано.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39752660
sql2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shuraken,

для расшифровки нужен закрытый ключ.
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39752675
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sql2012,

Это понятно, у меня сертификат с закрытым. Но дело в том, что расшифровка не происходит, если использовать GostDecryptSOAP.decryptMsg(aCertProv, aProvMsg). Первым параметром я указываю провайдера сертификата с закрытым ключом, вторым - ответ, полученный от ФСС. И подав зашифрованные данные на вход, я получаю их же на выходе. И у меня складывается ощущение, что эта функция просто не знает, как расшифровать.
Когда же я это делаю низкоуровневыми функциями, то ломаюсь с ошибкой "Плохие данные" при получении сессионного ключа.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
    CheckCryptoCall(CryptGetUserKey(ACryptoProvider, AT_KEYEXCHANGE, @hPrivateKey));

    // Формирование BLOB-ов публичного и сессионного ключей ФСС на основе зашифрованного ключа из ответа ФСС
    GetResponseKeysBlobs(ASOAPResponse, remotePublicKeyBlob, remoteSessionKeyBlob);

    // Получение ключа согласования импортом открытого ключа ФСС (отправителя)
    // на локальном закрытом ключе (получателя)
    CheckCryptoCall(CryptImportKey(ACryptoProvider, @remotePublicKeyBlob[0], Length(remotePublicKeyBlob), hPrivateKey, 0, @hAgreeKey));

    // Установка параметра PRO_EXPORT алгоритма ключа согласования
    keyParam := CALG_PRO_EXPORT;
    CheckCryptoCall(CryptSetKeyParam(hAgreeKey, KP_ALGID, @keyParam, 0));

    // Получение сессионного ключа импортом сессионного ключа ФСС (отправителя) на ключе согласования
    // Вот здесь и происходит ошибка.
    CheckCryptoCall(CryptImportKey(ACryptoProvider, @remoteSessionKeyBlob[0], Length(remoteSessionKeyBlob), hAgreeKey, 0, @hSessionKey));



И я пытаюсь разобраться, что надо подать на вход функции GostDecryptSOAP, чтобы получить расшифрованные данные, и в чём причина ошибки "плохие данные" при работе с низкоуровневыми функциями. В этом я и прошу помочь мне.
В аттаче dll и обёртка для делфи
...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39752789
maratvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shuraken,

Насколько помню в ответе от ФСС надо подменить их сертификат своим перед расшифровкой. Нашел вот такую процедуру. Попробуйте сделать что-то похожее.


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
function DecryptXml(AXml: IXmlDocument; const AOwnerCertName {это сертификат НАШЕЙ организации}: string): string;
var
  S: string;
  Node: IXmlNode;
begin
  Node := FindPath(AXml, '/SOAP-ENV:Envelope/SOAP-ENV:Body/xenc:EncryptedData/ds:KeyInfo/xenc:EncryptedKey/ds:KeyInfo/ds:X509Data/ds:X509Certificate');
  if Node = nil then
    Exit;
  Node.Text := GetCertCertificate(AOwnerCertName); 
  Node := FindPath(AXml, '/SOAP-ENV:Envelope/SOAP-ENV:Body/xenc:EncryptedData');
  S := Node.XML;
  S := DecryptSOAP(S); // вызов GostDecryptSOAP.decryptMsg
  S := '<?xml version=''1.0'' encoding=''UTF-8''?>' + S;
  Result := S;
end;

// получение сертификата в base64 кодировке по переданному имени сертификата
function GetCertCertificate(const ACertName: string): AnsiString;
var
  Cert: PCCERT_CONTEXT;
begin
  Cert := FindCertificate(ACertName);
  if Cert <> nil then
    try
      Result := EncodeBase64(Cert.pbCertEncoded, Cert.cbCertEncoded);
    finally
      CertFreeCertificateContext(Cert);
    end;
end;

...
Рейтинг: 0 / 0
Электронный больничный ЭЛН
    #39752842
Shuraken
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maratvgShuraken,

Насколько помню в ответе от ФСС надо подменить их сертификат своим перед расшифровкой. Нашел вот такую процедуру. Попробуйте сделать что-то похожее.



Спасибо за совет, попробовал, но получил ошибку "плохие данные". Использовал сертификат с закрытым ключом, который по структуре совпадает с сертификатом ФСС. Попробовал другие - та же самая картина. Интересно, а чьим открытым ключом они шифруют ответные сообщения. Я-то предполагал, что они расшифровывают закрытым ключом, берут открытый сертификат из подписи сообщения и шифруют им. И в этом случае в ответном сообщении я увижу открытый ключ своего сертификата. Но нет.
...
Рейтинг: 0 / 0
25 сообщений из 196, страница 4 из 8
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Электронный больничный ЭЛН
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]