logo
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

3 Страницы123>
Опции
К последнему сообщению К первому непрочитанному
Offline arkinform  
#1 Оставлено : 10 апреля 2018 г. 23:24:42(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
Здравствуйте!

Моя задача - реализовать шифрование XML, отправляемых на сервис ФСС, в нативном Windows приложении на Delphi.

Стандарт XML Encryption Syntax and Processing (W3C), шифрование сессионного ключа и данных происходит по алгоритму ГОСТ 28147-89.
Аналогичное шифрование на .NET сделали быстро и без проблем, а вот c нативной реализацией через Crypto API возникли трудности.

Схема реализации, которая была выбрана:
1. Сформировать исходный XML

2. Зашифровать буфер, содержащий XML, через функцию CryptEncryptMessage открытым ключом сертификата. На входе сертификат в формате DER (ACertificate) и буфер, содержащий XML (ASourceData). На выходе PKCS#7 Enveloped Data, содержащая параметры шифрования, ключи и зашифрованные данные.
Код:

function TCryptoApiController.EncryptData(const ACertificate,
  ASourceData: AnsiString): AnsiString;
var
  FCryptProv: HCRYPTPROV;
  FCertContext: PCCERT_CONTEXT;
  FCertArray: PCCERT_CONTEXT_ARRAY;
  FEncryptParams: CRYPT_ENCRYPT_MESSAGE_PARA;
  FEncryptSizeNeed: DWORD;
begin
  AcquireContext(@FCryptProv, nil, CRYPT_VERIFYCONTEXT or CRYPT_SILENT, '');
  try

    // получение сертификата
    FCertContext := FCertCreateCertificateContext(PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, @ACertificate[1], Length(ACertificate));

    if FCertContext = nil then
      RaiseLastCryptoApiError;

    try
      FillChar(FEncryptParams, SizeOf(FEncryptParams), 0);

      FEncryptParams.cbSize := SizeOf(CRYPT_ENCRYPT_MESSAGE_PARA);
      FEncryptParams.dwMsgEncodingType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
      FEncryptParams.hCryptProv := FCryptProv;
      FEncryptParams.ContentEncryptionAlgorithm.pszObjId := PAnsiChar(szOID_CP_GOST_28147);

      SetLength(FCertArray, 1);
      FCertArray[0] := FCertContext;

      // шифрование исходных данных
      if FCryptEncryptMessage(@FEncryptParams, 1, FCertArray, @ASourceData[1], Length(ASourceData), nil, @FEncryptSizeNeed) then
      begin
        SetLength(Result, FEncryptSizeNeed);
        FillChar(Result[1], FEncryptSizeNeed, 0);

        if not FCryptEncryptMessage(@FEncryptParams, 1, FCertArray, @ASourceData[1], Length(ASourceData), @Result[1], @FEncryptSizeNeed) then
          RaiseLastCryptoApiError;

        // When processing the data returned in the buffer of the pbEncryptedBlob, applications need to use the actual size of the data returned.
        // The actual size can be slightly smaller than the size of the buffer specified on input.
        SetLength(Result, FEncryptSizeNeed);

      end else
        RaiseLastCryptoApiError;

    finally
      if FCertContext <> nil then
        FCertFreeCertificateContext(FCertContext);
    end;

  finally
    ReleaseContext(FCryptProv);
  end
end


3. Из PKCS# Enveloped Data через ASN.1 парсер получить готовую структуру GostR3410-KeyTransport и записать в зашифрованный XML в параметр EncryptedData -> KeyInfo -> EncryptedKey -> CipherData в соответствии со стандартом https://tools.ietf.org/h...v-cryptopro-cpxmldsig-09

4. Из PKCS# Enveloped Data через ASN.1 парсер получить зашифрованные данные и вектор инициализации и записать их в зашифрованный XML в параметр EncryptedData -> CipherData в соответствии со тем же стандартом https://tools.ietf.org/h...v-cryptopro-cpxmldsig-09 (The resulting cipher text is prefixed by the IV. If included in XML output, it is then base64 encoded.)

В процессе реализации и чтения стандартов выяснил, что стандарт XML Encryption Syntax and Processing (W3C) предполагает использование "padding" перед шифрованием. Опытным путем выяснил, что функция CryptEncryptMessage "padding" не применяет (зашифровал 1 байт и на выходе в PKCS# Enveloped Data получил зашифрованные данные размером этот же 1 байт, хотя в случае "padding" они должны были быть выровнены до 8 байт).

Реализовал "padding" на своей стороне:
Код:

function MakePadding(const Data: AnsiString): AnsiString;
var
  FPaddingCount: Integer;
  FPaddingSuffix: AnsiString;
  I: Integer;
begin
  FPaddingCount := 8 - (Length(Data) mod 8);
  FPaddingSuffix := '';

  for I := 1 to FPaddingCount do
    FPaddingSuffix := FPaddingSuffix + AnsiChar(FPaddingCount);

  Result := Data + FPaddingSuffix;
end;


В итоге получил:
1. Зашифрованные данные PKCS# Enveloped Data https://lapo.it/asn1js/#...BFB8EB76A5731C17B77D2052
2. Зашифрованный XML, сформированный описанным выше методом, request.xml (во вложении)

Зашифрованные данные PKCS#7 Enveloped Data (п.1) без проблем расшифровываются через Crypto API функцию CryptDecryptMessage (в примерах указан сертификат ФСС, но я пробовал шифровать своим сертификатом, для которого у меня есть закрытый ключ, чтобы проверить расшифровку).

Но сформированный request.xml принимающий сервис ФСС расшифровать не может!

Для проверки я реализовал шифрование этого же исходного XML на .NET через библиотеку GostCryptography:
Код:

// CryptoPro CSP
GostCryptoConfig.ProviderType = ProviderTypes.CryptoPro;

// Создание объекта для шифрации XML
var encryptedXml = new GostEncryptedXml();

Console.Write(encryptedXml.Mode);

var certificate = new X509Certificate2(fileName: "C:\\Work\\test.cer");

var xmlDocument = new XmlDocument();
xmlDocument.Load("C:\\Work\\FSS\\request_sample.xml");

// Шифрование всего документа
var elementEncryptedData = encryptedXml.Encrypt(xmlDocument.DocumentElement, certificate);

var soapDocument = new XmlDocument();

var soapElement = soapDocument.CreateElement("soapenv:Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
soapDocument.AppendChild(soapElement);

var bodyElement = soapDocument.CreateElement("soapenv:Body", "http://schemas.xmlsoap.org/soap/envelope/");
soapElement.AppendChild(bodyElement);

// Замена элемента его зашифрованным представлением
GostEncryptedXml.ReplaceElement(bodyElement, elementEncryptedData, true);

soapDocument.Save("C:\\Work\\FSS\\request_sample_encrypted.xml");


Полученный request_sample_encrypted.xml (во вложении) без проблем принимается сервисом ФСС!

Я проверил:
- Размер и структура XML request.xml и request_sample_encrypted.xml полностью совпадают
- Проверил EncryptedData -> KeyInfo -> EncryptedKey -> CipherData через ASN.1 Viewer: структура, размеры параметров и OID полностью совпадают (понятно, что сами значения отличаются)
- Размер зашифрованных данных тоже совпадает

Попробовал зашифровать XML на своем сертификате через CryptEncryptMessage по описанной выше схеме, а расшифровать через .NET. Действительно, расшифровать не получается, возвращается ошибка "Плохие данные".

Подскажите, пожалуйста, в чем может быть проблема.

Вопросы:

1. Функция CryptEncryptMessage в приведенном мной примере шифрует данные по алгоритму urn:ietf:params:xml:ns:cpxmlsec:algorithms:gost28147 с упаковкой ключей urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001? или она реализует какой-то другой алгоритм? какими параметрами алгоритма шифрования можно управлять при использовании функции CryptEncryptMessage? Какие параметры используются по умолчанию? Странно, что моя структура GostR3410-KeyTransport полностью совпадает с рабочим примером.

2. Правильно я понимаю, что в моем примере PKCS#7 Enveloped Data (см. выше) вектор инициализации - это x"40A6B01F5F877B74" ? При записи EncryptedData -> CipherData в XML вектор инициализации нужно просто добавить перед зашифрованными данными x"93E4F5...", чтобы получилось x"40A6B01F5F877B7493E4F5..." и потом запаковать в Base64?

3. Почему функция CryptEncryptMessage не использует "padding"? Можно ли каким-то параметром включить для нее "padding"? (про CryptSetKeyParam и KP_PADDING я знаю, но здесь нет прямой работы с ключами) Правильно ли я реализовал "padding" на своей стороне?

Отредактировано пользователем 10 апреля 2018 г. 23:47:28(UTC)  | Причина: Не указана

Offline arkinform  
#2 Оставлено : 10 апреля 2018 г. 23:30:16(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
Не нашел, как приложить файлы, поэтому прикладывают примеры XML текстом:

request.xml:

Код:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gost28147"/>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001"/>
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <X509Data>
              <X509Certificate>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</X509Certificate>
            </X509Data>
          </KeyInfo>
          <CipherData>
            <CipherValue>MIGkMCgEIE/ehIaWxLiGJbntzJq2/X/6Ajt+zeooW5y4Fc/orD8MBATp3cUgoHgGByqFAwICHwGgYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARAEheo28OFcXA+T3jcp+NjdGBjXpFhZVIKcH4L05dd0y/6knYOA1huGv7ipujtprikMfV8bF7cQV/ps9lYgXyrEAQIGVw2Y0ivKMs=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>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</CipherValue>
      </CipherData>
    </EncryptedData>
  </soapenv:Body>
</soapenv:Envelope>


request_sample_encrypted.xml:

Код:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gost28147"/>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001"/>
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <X509Data>
              <X509Certificate>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</X509Certificate>
            </X509Data>
          </KeyInfo>
          <CipherData>
            <CipherValue>MIGkMCgEIBD/UCIYk/5IxsiyOwfZ7eOcmK/uC5I/1ysk7vcjp3UxBAT+6Dk9oHgGByqFAwICHwGgYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARAOVxB6TNPZxEFDOnrl8Z5OcOW9WhYWPQ4ekLuU9GZFeZJh0aL2LXZeHqriE2YXQCTHo+NarIQgd4p0LFEySvfgAQIhjkYyguWdvA=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>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</CipherValue>
      </CipherData>
    </EncryptedData>
  </soapenv:Body>
</soapenv:Envelope>

Отредактировано пользователем 10 апреля 2018 г. 23:39:45(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#3 Оставлено : 17 апреля 2018 г. 14:48:14(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
В CSP используется режим поточный шифр - паддинг не нужен.
IV, да - первые 8 байт.

Отредактировано пользователем 17 апреля 2018 г. 14:55:10(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в техподдержке
Offline arkinform  
#4 Оставлено : 17 апреля 2018 г. 15:27:17(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
На мой взгляд, я не получил полных ответов на свои вопросы (см. 3 вопроса в моем первом сообщении)

Цитата:
В CSP используется режим поточный шифр - паддинг не нужен.

Но в стандарте XML Encryption паддинг нужен, это значит, что его необходимо реализовывать самостоятельно до вызова функции шифрования в CSP?

И самый главный вопрос - "функция CryptEncryptMessage в приведенном мной примере шифрует данные по алгоритму urn:ietf:params:xml:ns:cpxmlsec:algorithms:gost28147 ??? с упаковкой ключей urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001 ???"

"Режим поточный шифр" соответствует этим алгоритмам или это другой режим? Если другой, то можно ли через CryptEncryptMessage шифровать в указанном в XML режиме? Если CryptEncryptMessage этого не умеет, то какие функции необходимо использовать?

Цитата:
IV, да - первые 8 байт.

Это я понял из стандарта https://tools.ietf.org/h...v-cryptopro-cpxmldsig-09
Мой вопрос был "Правильно я понимаю, что в моем примере PKCS#7 Enveloped Data https://lapo.it/asn1js/#...BFB8EB76A5731C17B77D2052 вектор инициализации - это x"40A6B01F5F877B74"?
Offline Максим Коллегин  
#5 Оставлено : 17 апреля 2018 г. 17:53:07(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Цитата:
вектор инициализации - это x"40A6B01F5F877B74

Да.
CryptEncryptMessage ничего не знает про эти идентификаторы xml алгоритмов, но в xmlenc используются похожие схемы.
Но вообще очень странный выбран механизм создания сообщения - разобрать pkcs#7 на части и превратить в xml.
А обратную задачу не пробовали решить: из xml собрать pkcs#7 и расшифровать?
Знания в базе знаний, поддержка в техподдержке
Offline Максим Коллегин  
#6 Оставлено : 17 апреля 2018 г. 18:23:48(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Потрассировал наш пример Xml.EncryptCertificate из КриптоПро .NET SDK:
паддинг выполняется перед шифрованием: Random bytes и в последнем байте длина ISO_10126
Ранее с xml шифрованием сталкиваться не приходилось, поэтому сразу подсказать не смог, прошу меня извинить.

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

Знания в базе знаний, поддержка в техподдержке
Offline arkinform  
#7 Оставлено : 17 апреля 2018 г. 20:02:51(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
Цитата:
Потрассировал наш пример Xml.EncryptCertificate из КриптоПро .NET SDK:
паддинг выполняется перед шифрованием: Random bytes и в последнем байте длина ISO_10126
Ранее с xml шифрованием сталкиваться не приходилось, поэтому сразу подсказать не смог, прошу меня извинить.

Спасибо, что вникли в суть проблемы. Я реализовал PKCS7 паддинг вместо ISO_10126 (пример кода в моем первом сообщении), но это не важно, потому что в PKCS7 все байты заполняются длиной паддинга, а в ISO_10126 только последний, а остальные случайными байтами, т.е. PKCS7 паддинг - это частный случай ISO_10126.

Цитата:
Но вообще очень странный выбран механизм создания сообщения - разобрать pkcs#7 на части и превратить в xml.

Этот вариант был выбран, потому что используется простая высокоуровневая функция CryptEncryptMessage, которая на выходе выдает готовую структуру GostR3410-KeyTransport, остается только взять ее из PKCS#7 Message. Второй вариант - использовать низкоуровневые функции шифрования, получить каждый параметр структуры GostR3410-KeyTransport отдельно и потом самому собрать GostR3410-KeyTransport, чтобы включить в XML в параметр EncryptedData -> KeyInfo -> EncryptedKey -> CipherData. Мне кажется, что этот вариант явно сложнее. Если вы знаете другие варианты, пишите.

Цитата:
А обратную задачу не пробовали решить: из xml собрать pkcs#7 и расшифровать?

Пока не пробовал. Технически собрать PKCS#7 из зашифрованной XML не проблема, но мне кажется, что пока я не смогу зашифровать корректно, пробовать расшифровать нет особого смысла. При этом я уверен, что PKCS#7 Message от функции CryptEncryptMessage без проблем расшифровывается функцией CryptDecryptMessage, т.е. проблема либо в том, что для XML нужно шифровать как-то по-другому, не так как делает CryptEncryptMessage, либо какой-то нюанс с форматом зашифрованных данных в XML (паддинг, порядок байтов и т.п.).

Мой текущий вариант берет исходный XML, делает паддинг до 8 байт, шифрует через CryptEncryptMessage, получает "сырые" зашифрованные данные из PKCS#7 Message, добавляет к ним префикс 8 байт IV и заворачивает в Base64. В итоге я получаю зашифрованные данные по длине идентичные варианту через Xml.EncryptCertificate в .NET (см. мое второе сообщение с примерами XML), но мой вариант .NET расшифровать не может.

Цитата:
CryptEncryptMessage ничего не знает про эти идентификаторы xml алгоритмов, но в xmlenc используются похожие схемы.

Я понимаю, что это идентификаторы именно для XML, но за ними ведь стоят конкретные алгоритмы и параметры шифрования.
Пока для меня остается открытым главный вопрос - функция CryptEncryptMessage использует те же алгоритмы и параметры шифрования, что Xml.EncryptCertificate из КриптоПро .NET SDK или нет? Можно ли как-то управлять параметрами CryptEncryptMessage?

P.S. В последнее время шифрование XML через Crypto API - это очень актуальный вопрос в связи с активным распространением сервисов ФСС и СМЭВ. Я прочитал много форумов, на которых люди бьются с аналогичными проблемами: в .NET все работает легко, а нативно через Crypto API реализовать не могут. Будет идеально, если у вас появятся какие-то примеры, как правильно зашифровать целиком простой XML файл через Crypto API.
Offline Максим Коллегин  
#8 Оставлено : 18 апреля 2018 г. 8:51:10(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Зашифруйте в адрес меня, я попробую потрассировать расшифрование.

Код:
MIICoDCCAk+gAwIBAgIKPbZvpgAAAI2zAjAIBgYqhQMCAgMwOjESMBAGCgmSJomT8ixkARkWAnJ1MRIwEAYKCZImiZPyLGQBGRYCY3AxEDAOBgNVBAMTB3Rlc3QtY2EwHhcNMTcwNjA1MDYwNTQyWhcNMjcwNjA1MTI0NTQyWjAUMRIwEAYDVQQDDAlnb3N0X3Rlc3QwYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARA1OlWsp/zFcQtdnHXs4O1/xmLdJ/ghhdlUoA+h923z8z3wL9N/nQ4d/mgK58XMu7L2INzfJnejpMji9bZR7jMAaOCAVkwggFVMA4GA1UdDwEB/wQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQU3AzBHbU4q+yOgu5vacDt20XbeYowHwYDVR0jBBgwFoAUngPwuJz8YNyKGB7oAN+oWzLNc3YwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL3ZtLXRlc3QtY2EuY3AucnUvQ2VydEVucm9sbC90ZXN0LWNhLmNybDCBrAYIKwYBBQUHAQEEgZ8wgZwwSwYIKwYBBQUHMAKGP2h0dHA6Ly92bS10ZXN0LWNhLmNwLnJ1L0NlcnRFbnJvbGwvdm0tdGVzdC1jYS5jcC5ydV90ZXN0LWNhLmNydDBNBggrBgEFBQcwAoZBZmlsZTovL1xcdm0tdGVzdC1jYS5jcC5ydVxDZXJ0RW5yb2xsXHZtLXRlc3QtY2EuY3AucnVfdGVzdC1jYS5jcnQwCAYGKoUDAgIDA0EAQ5N8qJ8M3P9cLjepMBtNObuJgCwN4ffm6cNNDY/hrjPsgt+5M0js/NyU6cDXjStms5A8wco8yswpZh11Lu09dA==
Знания в базе знаний, поддержка в техподдержке
Offline arkinform  
#9 Оставлено : 18 апреля 2018 г. 10:49:55(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
Зашифрованная вашим сертификатом XML:
Код:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#">
      <EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gost28147"/>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001"/>
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <X509Data>
              <X509Certificate>MIICoDCCAk+gAwIBAgIKPbZvpgAAAI2zAjAIBgYqhQMCAgMwOjESMBAGCgmSJomT8ixkARkWAnJ1MRIwEAYKCZImiZPyLGQBGRYCY3AxEDAOBgNVBAMTB3Rlc3QtY2EwHhcNMTcwNjA1MDYwNTQyWhcNMjcwNjA1MTI0NTQyWjAUMRIwEAYDVQQDDAlnb3N0X3Rlc3QwYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARA1OlWsp/zFcQtdnHXs4O1/xmLdJ/ghhdlUoA+h923z8z3wL9N/nQ4d/mgK58XMu7L2INzfJnejpMji9bZR7jMAaOCAVkwggFVMA4GA1UdDwEB/wQEAwIE8DATBgNVHSUEDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQU3AzBHbU4q+yOgu5vacDt20XbeYowHwYDVR0jBBgwFoAUngPwuJz8YNyKGB7oAN+oWzLNc3YwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL3ZtLXRlc3QtY2EuY3AucnUvQ2VydEVucm9sbC90ZXN0LWNhLmNybDCBrAYIKwYBBQUHAQEEgZ8wgZwwSwYIKwYBBQUHMAKGP2h0dHA6Ly92bS10ZXN0LWNhLmNwLnJ1L0NlcnRFbnJvbGwvdm0tdGVzdC1jYS5jcC5ydV90ZXN0LWNhLmNydDBNBggrBgEFBQcwAoZBZmlsZTovL1xcdm0tdGVzdC1jYS5jcC5ydVxDZXJ0RW5yb2xsXHZtLXRlc3QtY2EuY3AucnVfdGVzdC1jYS5jcnQwCAYGKoUDAgIDA0EAQ5N8qJ8M3P9cLjepMBtNObuJgCwN4ffm6cNNDY/hrjPsgt+5M0js/NyU6cDXjStms5A8wco8yswpZh11Lu09dA==</X509Certificate>
            </X509Data>
          </KeyInfo>
          <CipherData>
            <CipherValue>MIGkMCgEIICGF38DhwPxD1ZZ6yBPgPSAMBLW1FmQ5voizZ/lX3DhBASfZ79AoHgGByqFAwICHwGgYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARASGgDq3JwyhbhlCF4EYm/XbMgKu5SQ+Juu8osgS8fgqUqqvf76Vh0vCGSbzCrtobqLeC95JRjL9axy7hnApScCwQIbou6weExn1g=</CipherValue>
          </CipherData>
        </EncryptedKey>
      </KeyInfo>
      <CipherData>
        <CipherValue>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</CipherValue>
      </CipherData>
    </EncryptedData>
  </soapenv:Body>
</soapenv:Envelope>


Соответствующий PKCS#7 Enveloped Message от функции CryptEncryptMessage:
Код:

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
Offline Максим Коллегин  
#10 Оставлено : 18 апреля 2018 г. 13:18:36(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Принял, постараюсь сегодня посмотреть.
Знания в базе знаний, поддержка в техподдержке
Offline Максим Коллегин  
#11 Оставлено : 18 апреля 2018 г. 15:13:15(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Ключ получается нормально, но ХML ожидает шифрование в CBC. А CryptEncryptMessage шифрует CFB.
Если указать вот так, то проходит почти расшифровывает.
Код:
EncryptedXml exml = new EncryptedXml(Doc);
exml.Mode = System.Security.Cryptography.CipherMode.CFB;
exml.Padding = System.Security.Cryptography.PaddingMode.None;

Но спотыкается на падинге - не нравится символ 0x6.

Отредактировано пользователем 18 апреля 2018 г. 15:36:51(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в техподдержке
Offline arkinform  
#12 Оставлено : 18 апреля 2018 г. 15:53:39(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
Цитата:
ХML ожидает шифрование в CBC. А CryptEncryptMessage шифрует CFB.

Вот, это уже прогресс с пониманием проблемы. Можно ли использовать функцию CryptEncryptMessage для шифрования CBC? Если нет, то какие функции проще всего использовать для шифрования CBC?

Цитата:
Но спотыкается на падинге - не нравится символ 0x6

Я использовал паддинг, попробуйте System.Security.Cryptography.PaddingMode = PKCS7
Offline Максим Коллегин  
#13 Оставлено : 18 апреля 2018 г. 16:02:15(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Для CFB паддинг не разрешает сам .NET.
У нас нет даже оид-идентификатора для ГОСТ 28147 CBC, поэтому в текущий момент CryptEncryptMessage использовать не получится.
Знания в базе знаний, поддержка в техподдержке
Offline Максим Коллегин  
#14 Оставлено : 18 апреля 2018 г. 16:08:35(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Вижу несколько вариантов решения исходной задачи на уровне CryptoApi
1. Для нативного xmldsig мы используем xmlsec\mscrypto, но xmlenc в нём ни разу не использовали - не факт, что он живой - можете попробовать.
2. Завести новый никем не поддерживаемый идентификатор для ГОСТ CMS с CBC и поддержать работу с ним в нашем криптопровайдере (в 5.0)
3. Собрать xml по вашему сценарию из поста #7
Знания в базе знаний, поддержка в техподдержке
Offline arkinform  
#15 Оставлено : 18 апреля 2018 г. 17:05:35(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
Цитата:
1. Для нативного xmldsig мы используем xmlsec\mscrypto, но xmlenc в нём ни разу не использовали - не факт, что он живой - можете попробовать.

Этот вариант мне не очень нравится, потому что используется какая-то отдельная open source библиотека без полноценной поддержки, нужно собирать самому их исходников и т.п. Последние сборки libxml ftp://ftp.zlatkovic.com/libxml/ от 2011 года. Также мне нужна сборка под Win64, не уверен, что она вообще живая.

Цитата:
2. Завести новый никем не поддерживаемый идентификатор для ГОСТ CMS с CBC и поддержать работу с ним в нашем криптопровайдере (в 5.0)

Мне помимо КриптоПро нужна еще поддержка VipNet + этот вариант явно не самый быстрый, но для будущих поколений было бы полезно :)

Цитата:
3. Собрать xml по вашему сценарию из поста #7

Если вы имеете в виду "использовать низкоуровневые функции шифрования...", то я склоняюсь к этому варианту.
Вы можете дать примеры шифрования CBC низкоуровневыми функциям? Это бы очень помогло.
Offline Максим Коллегин  
#16 Оставлено : 19 апреля 2018 г. 8:30:55(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 11 раз
Поблагодарили: 484 раз в 440 постах
Для шифрования CBC ключу 28147 нужно установить:
CryptSetKeyParam( KP_MODE, CRYPT_MODE_CBC)
Знания в базе знаний, поддержка в техподдержке
Offline arkinform  
#17 Оставлено : 24 апреля 2018 г. 17:49:11(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
В итоге я реализовал шифрование XML для сервисов ФСС через низкоуровневые функции Crypto API, поделюсь своим опытом, потому что структурированной информации в интернете по этой теме очень мало.

Далее описываю схему шифрования XML именно для сервисов ФСС (для других, возможно, будет отличаться).

Важные моменты:

- Для шифрования в XML необходимо использовать режим шифрования CBC (высокоуровневые функции CryptEncryptMessage и CryptDecryptMessage этот режим не поддерживают)
- При шифровании необходимо использовать паддинг исходных данных в режиме ISO10126

Зашифрованный XML файл содержит 3 важных сегмента (примеры смотри выше в переписке):

1. Зашифрованные данные (EncryptedData -> KeyInfo -> EncryptedKey -> CipherData)
1.1 "Сырые" зашифрованные данные, закодированные в Base64
1.2 Первые 8 байт - вектор инициализации (IV)

2. Зашифрованный сессионный ключ и параметры шифрования (EncryptedData -> KeyInfo -> EncryptedKey -> CipherData)
2.1 Значение представляет собой ASN.1 структуру GostR3410-KeyTransport, закодированную в Base64
2.2 Внутреннюю структуру можно посмотреть с помощью любого ASN.1 просмотровщика (например, на сайте https://lapo.it/asn1js)
- OCTET STRING (32 byte) - зашифрованный сессионный ключ
- OCTET STRING (4 byte) - MAC сессионного ключа
- OCTET STRING (64 byte) - открытый ключ отправителя
- OCTET STRING (8 byte) - синхропосылка (UKM)

3. Сертификат, которым будет зашифровано ответное сообщение (EncryptedData -> KeyInfo -> EncryptedKey -> KeyInfo)
3.1 Сертификат в формате X.509, закодированный в Base64

Принцип шифрования XML:

- Берем исходный XML файл и сертификат получателя, которым будут зашифрованы данные (в моем случае это сертификат ФСС)
- Экспортируем открытый ключ получателя из сертификата ФСС в PUBLICKEYBLOB
- Генерируем эфемерную ключевую пару (закрытый и открытый ключ отправителя)
- Экспортируем открытый ключ отправителя в PUBLICKEYBLOB и сохраняем последние 64 байта (потребуются для записи в структуру GostR3410-KeyTransport)
- Получаем ключ согласования импортом открытого ключа получателя на эфемерном ключе
- Создаем случайный сессионный ключ CALG_G28147
- Экспортируем созданный сессионный ключ в _CRYPT_SIMPLEBLOB на ключе согласования
- Получаем из структуры _CRYPT_SIMPLEBLOB значение зашифрованного сессионного ключа, MAC и синхропосылку (SV)
- Получаем вектор инициализации сессионного ключа
- Устанавливаем режим шифрования CBC и паддинг ISO10126
- Шифруем данные исходного XML файла блоками по 8 байт
- Добавляем к зашифрованным данным в начало вектор инициализации
- Собираем структуру GostR3410-KeyTransport из зашифрованного сессионного ключа, MAC, синхропосылки и открытого ключа отправителя
- Создаем новый XML файл со структурой EncryptedData (см. примеры выше в переписке)

Принцип расшифровки XML:

- Берем зашифрованный XML файл и парсим из него параметры структуры EncryptedData
- Получаем свой закрытый ключ AT_KEYEXCHANGE для расшифровки
- Собираем PUBLICKEYBLOB из статической части и открытого ключа
- Получаем ключ согласования импортом открытого ключа отправителя на своем закрытом ключе
- Собираем структуру _CRYPT_SIMPLEBLOB из статической части, сессионного ключа, MAC и синхропосылки
- Получаем сессионный ключ импортом зашифрованного сессионного ключа на ключе согласования
- Устанавливаем вектор инициализации
- Устанавливаем режим шифрования CBC и паддинг ISO10126
- Расшифровываем данные блоками по 8 байт и получаем исходный XML файл

Пример шифрования буфера низкоуровневыми функциями на Delphi (предполагается, что дальнейшую упаковку параметров в структуру GostR3410-KeyTransport и создание зашифрованного XML читатель сможет выполнить самостоятельно):

Код:

function TCryptoApiController.EncryptData(
      const ACertificate: AnsiString; // сертификат для шифрования в формате DER
      const ASourceData: AnsiString; // исходные данные
      out APublicKey: AnsiString; // открытый ключ отправителя
      out ASessionKey: AnsiString; // зашифрованный сессионный ключ
      out ASessionSV: AnsiString; // синхропосылка (UKM)
      out ASessionMAC: AnsiString; // MAС сессионного ключа
      out AInitVector: AnsiString; // вектор инициализации
      const ACipherMode: TCryptoCipherMode = ccm_CBC; // режим шифрования
      const APaddingMode: TCryptoPaddingMode = cpm_ISO10126 // режим паддинга
    ): AnsiString;
const
  ENCRYPT_BLOCK_LENGTH: DWORD = 8;
var
  FCryptProv: HCRYPTPROV;
  FCertContext: PCCERT_CONTEXT;
  FPublicKey: HCRYPTKEY;
  FSessionKeyBlob: AnsiString;
  FSenderPublicKeyBlob: AnsiString;
  FRecipientPublicKeyBlob: AnsiString;
  FEphemeralKey: HCRYPTKEY;
  FAgreeKey: HCRYPTKEY;
  FKeyLenNeed: DWORD;
  FSessionKey: HCRYPTKEY;
  FSourcePos: DWORD;
  FSourceDataLen: DWORD;
  FEncryptBuffer: AnsiString;
  FEncryptDataLen: DWORD;
  FEncryptBufferLen: DWORD;
  FEncryptFinal: LongBool;
begin
  CryptoInitialize;
  try
    CryptoLogMessage(CLM_ENCRYPT_DATA);

    AcquireContext(@FCryptProv, nil, CRYPT_VERIFYCONTEXT or CRYPT_SILENT, '');
    try

      // получение сертификата
      FCertContext := FCertCreateCertificateContext(PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, @ACertificate[1], Length(ACertificate));

      if FCertContext = nil then
        RaiseLastCryptoApiError;

      try
        // импорт информации по открытому ключу
        if FCryptImportPublicKeyInfoEx(FCryptProv, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, @FCertContext.pCertInfo.SubjectPublicKeyInfo, 0, 0, nil, @FPublicKey) then
        try

          // экспорт открытого ключа получателя в BLOB
          if FCryptExportKey(FPublicKey, 0, PUBLICKEYBLOB, 0, nil, @FKeyLenNeed) then
          begin
            SetLength(FRecipientPublicKeyBlob, FKeyLenNeed);

            if not FCryptExportKey(FPublicKey, 0, PUBLICKEYBLOB, 0, @FRecipientPublicKeyBlob[1], @FKeyLenNeed) then
              RaiseLastCryptoApiError;
          end;

        finally
          if not FCryptDestroyKey(FPublicKey) then
            RaiseLastCryptoApiError;
        end

        else
          RaiseLastCryptoApiError;

      finally
        if FCertContext <> nil then
          FCertFreeCertificateContext(FCertContext);
      end;

      // генерация эфемерной ключевой пары
      if FCryptGenKey(FCryptProv, CALG_DH_EL_EPHEM, CRYPT_EXPORTABLE, @FEphemeralKey) then
      try

        // экспорт открытого ключа отправителя в BLOB
        if FCryptExportKey(FEphemeralKey, 0, PUBLICKEYBLOB, 0, nil, @FKeyLenNeed) then
        begin
          SetLength(FSenderPublicKeyBlob, FKeyLenNeed);

          if not FCryptExportKey(FEphemeralKey, 0, PUBLICKEYBLOB, 0, @FSenderPublicKeyBlob[1], @FKeyLenNeed) then
            RaiseLastCryptoApiError;

          // получаем значение открытого ключа отправителя из PUBLICKEYBLOB
          APublicKey := Copy(FSenderPublicKeyBlob, Length(FSenderPublicKeyBlob) - 64 + 1, 64);
        end;

        // получение ключа согласования импортом открытого ключа получателя
        // на эфемерном ключе
        if FCryptImportKey(FCryptProv, @FRecipientPublicKeyBlob[1], Length(FRecipientPublicKeyBlob), FEphemeralKey, 0, @FAgreeKey) then
        try

          // установление PRO_EXPORT алгоритма ключа согласования
          if not FCryptSetKeyParam(FAgreeKey, KP_ALGID, @CALG_PRO_EXPORT, 0) then
            RaiseLastCryptoApiError;

          // создание случайного сессионного ключа
          if FCryptGenKey(FCryptProv, CALG_G28147, CRYPT_EXPORTABLE, @FSessionKey) then
          try

            // экспорт сессионного ключа в BLOB
            if FCryptExportKey(FSessionKey, FAgreeKey, SIMPLEBLOB, 0, nil, @FKeyLenNeed) then
            begin
              SetLength(FSessionKeyBlob, FKeyLenNeed);

              // экспорт сессионного ключа на ключе согласования
              if not FCryptExportKey(FSessionKey, FAgreeKey, SIMPLEBLOB, 0, @FSessionKeyBlob[1], @FKeyLenNeed) then
                RaiseLastCryptoApiError;

              (*
              FSessionKeyBlob = CRYPT_SIMPLEBLOB
                bType               : offset 1,  size 1
                bVersion            : offset 2,  size 1
                reserved            : offset 3,  size 2
                aiKeyAlg            : offset 5,  size 4
                Magic               : offset 9,  size 4
                EncryptKeyAlgId     : offset 13, size 4
                bSV (bUKM)          : offset 17, size 8
                bEncryptedKey       : offset 25, size 32
                bMacKey             : offset 57, size 4
                bEncryptionParamSet : offset 61
              end;
              *)

              ASessionSV  := Copy(FSessionKeyBlob, 17, 8);
              ASessionKey := Copy(FSessionKeyBlob, 25, 32);
              ASessionMAC := Copy(FSessionKeyBlob, 57, 4);
            end

            else
              RaiseLastCryptoApiError;

            // получение вектора инициализации
            if FCryptGetKeyParam(FSessionKey, KP_IV, nil, @FKeyLenNeed, 0) then
            begin
              SetLength(AInitVector, FKeyLenNeed);

              if not FCryptGetKeyParam(FSessionKey, KP_IV, @AInitVector[1], @FKeyLenNeed, 0) then
                RaiseLastCryptoApiError;

            end else
              RaiseLastCryptoApiError;

            // зашифрованные данные
            Result := '';

            // режим шифрования CBC
            if not FCryptSetKeyParam(FSessionKey, KP_MODE, @CryptoCipherModeConst[ACipherMode], 0) then
              RaiseLastCryptoApiError;

            // режим паддинга
            if not FCryptSetKeyParam(FSessionKey, KP_PADDING, @CryptoPaddingModeConst[APaddingMode], 0) then
              RaiseLastCryptoApiError;

            FSourceDataLen := Length(ASourceData);
            FSourcePos := 1;

            // шифрование блоками по 8 байт
            while FSourcePos <= FSourceDataLen do
            begin
              // временный буфер с исходными данными для шифрования
              FEncryptBuffer := Copy(ASourceData, FSourcePos, ENCRYPT_BLOCK_LENGTH);
              FEncryptBufferLen := Length(FEncryptBuffer);
              FEncryptDataLen := FEncryptBufferLen;

              // последний блок данных
              FEncryptFinal := (FSourcePos + ENCRYPT_BLOCK_LENGTH) > FSourceDataLen;

              // получение размера буфера с учетом возможного паддинга
              if not FCryptEncrypt(FSessionKey, 0, FEncryptFinal, 0, nil, FEncryptBufferLen, 0) then
                RaiseLastCryptoApiError;

              // установка размера буфера
              SetLength(FEncryptBuffer, FEncryptBufferLen);

              // шифрование буфера данных
              if not FCryptEncrypt(FSessionKey, 0, FEncryptFinal, 0, @FEncryptBuffer[1], FEncryptDataLen, FEncryptBufferLen) then
                RaiseLastCryptoApiError;

              // накопление зашифрованных данных
              Result := Result + FEncryptBuffer;

              // переход к следующему блоку
              FSourcePos := FSourcePos + ENCRYPT_BLOCK_LENGTH;
            end

          finally
            if not FCryptDestroyKey(FSessionKey) then
              RaiseLastCryptoApiError;
          end

          else
            RaiseLastCryptoApiError;

        finally
          if not FCryptDestroyKey(FAgreeKey) then
            RaiseLastCryptoApiError;
        end

        else
          RaiseLastCryptoApiError;

      finally
        if not FCryptDestroyKey(FEphemeralKey) then
          RaiseLastCryptoApiError;
      end

      else
        RaiseLastCryptoApiError;

    finally
      ReleaseContext(FCryptProv);
    end

  finally
    CryptoFinalize;
  end;
end;



Пример расшифровки буфера низкоуровневыми функциями на Delphi (предполагается, что предварительный парсинг зашифрованного XML и распаковку параметров из структуры GostR3410-KeyTransport читатель сможет выполнить самостоятельно):

Код:

function TCryptoApiController.DecryptData(
      const AKeyID: AnsiString; // идентификатор контейнера
      const AUserPIN: AnsiString;  // PIN код
      const AEncryptedData: AnsiString; // зашифрованные данные
      const APublicKey: AnsiString; // открытый ключ отправителя
      const ASessionKey: AnsiString; // зашифрованный сессионный ключ
      const ASessionSV: AnsiString; // синхропосылка (UKM)
      const ASessionMAC: AnsiString; // MAС сессионного ключа
      const AInitVector: AnsiString; // вектор инициализации
      const ACipherMode: TCryptoCipherMode = ccm_CBC; // режим шифрования
      const APaddingMode: TCryptoPaddingMode = cpm_ISO10126 // режим паддинга
    ): AnsiString;
const
  DECRYPT_BLOCK_LENGTH: DWORD = 8;
var
  FCryptProv: HCRYPTPROV;
  FPublicKeyBlob: AnsiString;
  FSessionKeyBlob: AnsiString;
  FPrivateKey: HCRYPTKEY;
  FAgreeKey: HCRYPTKEY;
  FSessionKey: HCRYPTKEY;
  FSourcePos: DWORD;
  FSourceDataLen: DWORD;
  FDecryptBuffer: AnsiString;
  FDecryptBufferLen: DWORD;
  FDecryptFinal: LongBool;
begin
  if AKeyID = '' then
    RaiseCryptoException(CLE_CKA_ID_IS_EMPTY);

  CryptoInitialize;
  try
    CryptoLogMessage(CLM_DECRYPT_DATA);

    AcquireContext(@FCryptProv, PWideChar(WideString(AKeyID)), CRYPT_SILENT, AUserPIN);
    try

      // получение закрытого ключа
      if FCryptGetUserKey(FCryptProv, AT_KEYEXCHANGE, @FPrivateKey) then
      try

        // сборка PublicKey BLOB из статической части и открытого ключа
        FPublicKeyBlob :=
          #$06#$20#$00#$00#$23#$2E#$00#$00#$4D#$41#$47#$31#$00#$02#$00#$00#$30#$12 +
          #$06#$07#$2A#$85#$03#$02#$02#$24#$00#$06#$07#$2A#$85#$03#$02#$02#$1E#$01 +
          APublicKey;

        // получение ключа согласования импортом открытого ключа отправителя
        // на закрытом ключе
        if FCryptImportKey(FCryptProv, @FPublicKeyBlob[1], Length(FPublicKeyBlob), FPrivateKey, 0, @FAgreeKey) then
        try

          // установление PRO_EXPORT алгоритма ключа согласования
          if not FCryptSetKeyParam(FAgreeKey, KP_ALGID, @CALG_PRO_EXPORT, 0) then
            RaiseLastCryptoApiError;

          (*
          FSessionKeyBlob = CRYPT_SIMPLEBLOB
            bType               : offset 1,  size 1
            bVersion            : offset 2,  size 1
            reserved            : offset 3,  size 2
            aiKeyAlg            : offset 5,  size 4
            Magic               : offset 9,  size 4
            EncryptKeyAlgId     : offset 13, size 4
            bSV (bUKM)          : offset 17, size 8
            bEncryptedKey       : offset 25, size 32
            bMacKey             : offset 57, size 4
            bEncryptionParamSet : offset 61
          end;
          *)

          // сборка SessionKey BLOB из статической части и параметров сессионного ключа
          FSessionKeyBlob :=
            #$01#$20#$00#$00#$1E#$66#$00#$00#$FD#$51#$4A#$37#$1E#$66#$00#$00 +
            ASessionSV + ASessionKey + ASessionMAC +
            #$30#$09#$06#$07 + // ASN.1 Sequence + OID Header
            #$2A#$85#$03#$02#$02#$1F#$01; // OID_GOST_R28147_89_CryptoPro_A_ParamSet 1.2.643.2.2.31.1

          // получение сессионного ключа импортом зашифрованного сессионного ключа
          // на ключе согласования
          if FCryptImportKey(FCryptProv, @FSessionKeyBlob[1], Length(FSessionKeyBlob), FAgreeKey, 0, @FSessionKey) then
          try
            // расшифрованные данные
            Result := '';

            // установка вектора инициализации
            if not FCryptSetKeyParam(FSessionKey, KP_IV, @AInitVector[1], 0) then
              RaiseLastCryptoApiError;

            // режим шифрования CBC
            if not FCryptSetKeyParam(FSessionKey, KP_MODE, @CryptoCipherModeConst[ACipherMode], 0) then
              RaiseLastCryptoApiError;

            // режим паддинга
            if not FCryptSetKeyParam(FSessionKey, KP_PADDING, @CryptoPaddingModeConst[APaddingMode], 0) then
              RaiseLastCryptoApiError;

            FSourceDataLen := Length(AEncryptedData);
            FSourcePos := 1;

            // расщифровка блоками по 8 байт
            while FSourcePos <= FSourceDataLen do
            begin
              // временный буфер с исходными данными для расшифровки
              FDecryptBuffer := Copy(AEncryptedData, FSourcePos, DECRYPT_BLOCK_LENGTH);
              FDecryptBufferLen := Length(FDecryptBuffer);

              // последний блок данных
              FDecryptFinal := (FSourcePos + DECRYPT_BLOCK_LENGTH) > FSourceDataLen;

              // расшифровка буфера данных
              if not FCryptDecrypt(FSessionKey, 0, FDecryptFinal, 0, @FDecryptBuffer[1], FDecryptBufferLen) then
                RaiseLastCryptoApiError;

              // обновление размера буфера на реальный размер расшифрованных данных
              SetLength(FDecryptBuffer, FDecryptBufferLen);

              // накопление рашифрованных данных
              Result := Result + FDecryptBuffer;

              // переход к следующему блоку
              FSourcePos := FSourcePos + DECRYPT_BLOCK_LENGTH;
            end

          finally
            if not FCryptDestroyKey(FSessionKey) then
              RaiseLastCryptoApiError;
          end

          else
            RaiseLastCryptoApiError;

        finally
          if not FCryptDestroyKey(FAgreeKey) then
            RaiseLastCryptoApiError;
        end

        else
          RaiseLastCryptoApiError;

      finally
        if not FCryptDestroyKey(FPrivateKey) then
          RaiseLastCryptoApiError;
      end

      else
        RaiseLastCryptoApiError;

    finally
      ReleaseContext(FCryptProv);
    end

  finally
    CryptoFinalize;
  end;
end;

thanks 1 пользователь поблагодарил arkinform за этот пост.
GreyGoblin оставлено 28.09.2018(UTC)
Offline arkinform  
#18 Оставлено : 27 апреля 2018 г. 15:35:24(UTC)
arkinform

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

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

Поблагодарили: 2 раз в 2 постах
Замечания по шифрованию XML через VipNet CSP

Описанные мной принципы шифрования и примеры в целом работоспособны в VipNet CSP, но есть одна проблема - судя по всему VipNet CSP не поддерживает режим паддинга ISO10126_PADDING. Для шифрования запроса в ФСС это обходится указанием KP_PADDING = PKCS5_PADDING, сервис ФСС принимает такие запросы, а вот с расшифровкой сложнее. Зашифрованный ответ от ФСС не расшифровывается через VipNet CSP из-за ошибки вызова CryptDecrypt на последнем блоке (Final = true). Сами данные успешно расшифровываются, то функция явно выдает ошибку на этапе обработки паддинга. Аналогичная проблема описана на форуме в теме https://www.cryptopro.ru...aspx?g=posts&m=53984 , но правильнее не просто игнорировать данную ошибку, а обработать паддинг вручную:
Код:

...
// расшифровка буфера данных
if not FCryptDecrypt(FSessionKey, 0, FDecryptFinal, 0, @FDecryptBuffer[1], FDecryptBufferLen) then
begin
  // ручная обработка паддинга для VipNet CSP
  // https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=53984
  if (ProviderType = cpt_CSP_VipNet_GOST) and FDecryptFinal and
     (APaddingMode in [cpm_PKCS5, cpm_ISO10126, cpm_X923]) and (FDecryptBufferLen = DECRYPT_BLOCK_LENGTH) then
  begin
    // количество байт паддинга в последнем байте блока
    FDecryptBufferLen := FDecryptBufferLen - Ord(FDecryptBuffer[FDecryptBufferLen]);
  end

  else
    RaiseLastCryptoApiError;
end;
...
thanks 1 пользователь поблагодарил arkinform за этот пост.
Андрей Писарев оставлено 27.04.2018(UTC)
Offline not_x  
#19 Оставлено : 29 мая 2018 г. 2:06:31(UTC)
not_x

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

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

В КриптоПро CSP 3.6.7777 ISO10126_PADDING почему-то выдаёт ошибку на последнем блоке (CryptEncrypt( ..., ..., FEncryptFinal=1,...), ссоветственно использовалось PKCS5_PADDING (выставлено по умолчанию http://cpdn.cryptopro.ru...0278e45eb1994c38161.html )

Шифрование/расшифрование можно проводить не деля данные по блокам. Соответсвенно, вместо:


...
// шифрование блоками по 8 байт
while FSourcePos <= FSourceDataLen do
begin
...
end

Достаточно примерно так:
FEncryptBuffer := Copy(ASourceData, 1, FSourceDataLen)

// получение размера буфера с учетом возможного паддинга всего буфера
if not FCryptEncrypt(FSessionKey, 0, 1, 0, nil, FSourceDataLen, 0) then
RaiseLastCryptoApiError;

// установка размера буфера
SetLength( FEncryptBuffer, FSourceDataLen);

// шифрование буфера данных
if not FCryptEncrypt(FSessionKey, 0, 1, 0, @FEncryptBuffe[1], FSourceDataLen, FSourceDataLen) then
RaiseLastCryptoApiError;



При расшифровании вместо:
...
// расщифровка блоками по 8 байт
while FSourcePos <= FSourceDataLen do
begin
...
end

соотвественно:
FEncryptBuffer := Copy(ASourceData, 1, FSourceDataLen)

if not FCryptDecrypt(FSessionKey, 0, 1, 0, @FDecryptBuffer[1], FSourceDataLe) then
RaiseLastCryptoApiError;

SetLength(FDecryptBufferr, FSourceDataLe);

Отредактировано пользователем 29 мая 2018 г. 3:44:53(UTC)  | Причина: Не указана

Offline not_x  
#20 Оставлено : 29 мая 2018 г. 7:30:26(UTC)
not_x

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

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

В КриптоПро CSP 3.6.7777 ISO10126_PADDING дополнение (padding) при шифрование нужно формировать вручную и добавлять к данным (соответственно CryptEncrypt для "получения размера буфера с учетом возможного паддинга" бессмысленно - значения SourceDataLen всегда = 0). Похоже, что аналогичная картина в VipNet CSP
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
3 Страницы123>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.