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

Уведомление

Icon
Error

2 Страницы<12
Опции
К последнему сообщению К первому непрочитанному
Offline PicoMed  
#11 Оставлено : 16 декабря 2025 г. 18:00:09(UTC)
PicoMed

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

Группы: Участники
Зарегистрирован: 10.08.2019(UTC)
Сообщений: 6

Фрагмент кода, который расшифровывает пакет (убрана обработка ошибок и декларация переменных):

Код:
//transportKey, aDataText = base64 encoded binnary
function DecryptSOAPResponse( const transportKey, aDataText : string ): widestring;
begin
  // Получение локального закрытого ключа
  CryptGetUserKey(CryptoProvider, AT_KEYEXCHANGE, @hPrivateKey);

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

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

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

  // Получение сессионного ключа импортом сессионного ключа ФСС (отправителя) на ключе согласования
  CryptImportKey(CryptoProvider,
          @remoteSessionKeyBlob[0], Length(remoteSessionKeyBlob),
          hAgreeKey, 0, @hSessionKey);

  // Установка режима шифрования CBC
  keyParam := CRYPT_MODE_CBC;
  CryptSetKeyParam(hSessionKey, KP_MODE, @keyParam, 0);

  // Установка режима паддинга
  keyParam := 0;
  CryptSetKeyParam(hSessionKey, KP_PADDING, @keyParam, 0);

  // Получение зашифрованных данных из ответа ФСС
  // удаляем переносы строк, удаляем смещения Tab, переводим base64 в TBytes
  responseData := DecodeBytes( DeleteOther( aDataText ) );

  // Получение вектора инициализации (первые 8 байт ответа)
  initVector := Copy(responseData, 0, 8);
  // Получение зашифрованного запроса
  decryptedData := Copy(responseData, 8, Length(responseData) - 8);

  // Установка вектора инициализации
  CryptSetKeyParam(hSessionKey, KP_IV, @initVector[0], 0);

  // Определение размера буфера зашифрованного запроса
  decryptedDataLen := Length(decryptedData);

  // Расшифровка данных запроса  ---- вот здесь и получаем "Плохие данные"
  CryptDecrypt(hSessionKey, 0, true, 0, @decryptedData[0], @decryptedDataLen);

  // Обновление размера буфера расшифрованных данных
  SetLength(decryptedData, decryptedDataLen);

  // Формирование конечного содержания (устранение последствий паддинга и т.п.)
  Result := CreateDecryptedContent(decryptedData);
end;



// Формирование BLOB-ов публичного и сессионного ключей ФСС на основе зашифрованного ключа из ответа ФСС
procedure GetResponseKeysBlobs(const transportKey : string;
                        out APublicKeyBlob: TBytes; out ASessionKeyBlob: TBytes);
var
  transport, publicKey, sessionKey, sessionSV, sessionMAC: TBytes;
begin
  // удаляем переносы строк, удаляем смещения Tab, переводим base64 в TBytes
  transport := DecodeBytes( DeleteOther(transportKey) );
  publicKey := Copy(transport, 98, 64);  // 98, 64 открытый ключ отправителя
  sessionKey := Copy(transport, 7, 32);  // 7, 32 зашифрованный сессионный ключ
  sessionMAC := Copy(transport, 41, 4);  // 41, 4 MAC сессионного ключа
  sessionSV := Copy(transport, 164, 8);  // 164, 8  синхропосылка (UKM)

  APublicKeyBlob := bytesMerge( [
      Array2Dyn([
       $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, $13,
        $06, $07, $2A, $85, $03, $02, $02, $24, $00,
        $06, $08, $2A, $85, $03, $07, $01, $01, $02, $02
      ]), publicKey ] );


  ASessionKeyBlob := bytesMerge( [
      Array2Dyn([
       $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,
      Array2Dyn([// ASN.1 Sequence + OID Header
         $30 ,$0B ,$06 ,$09,
       // OID_GOST_R28147_89_CryptoPro_A_ParamSet 1.2.643.7.1.2.5.1.1
       $2A ,$85 ,$03 ,$07 ,$01 ,$02 ,$05, $01, $01
      ])]);
end;

Отредактировано пользователем 16 декабря 2025 г. 18:08:35(UTC)  | Причина: Не указана

Offline Сонина Лолита  
#12 Оставлено : 18 декабря 2025 г. 10:27:48(UTC)
Сонина Лолита

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

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

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 26 раз в 22 постах
Добрый день!

В коде есть странное место:
Код:
  // Установка режима паддинга
  keyParam := 0;
  CryptSetKeyParam(hSessionKey, KP_PADDING, @keyParam, 0);


Режима паддинга со значением 0 не существует. Если необходимо, чтобы провайдер никак не пытался интерпретировать паддинг, нужно передавать значение ZERO_PADDING.
Можете проверить, как изменится поведение, если изменить значение?
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Сонина Лолита за этот пост.
nickm оставлено 19.12.2025(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (2)
2 Страницы<12
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.