Доработка кода серверной части прикладного ПО для реализации прикладных сценариев

Перед чтением этого раздела рекомендуется ознакомиться с описанием сценариев использования Антифрод-терминала. В данном разделе даны некоторые пояснения и детализации к сценариям.

Для интеграции Антифрод-терминала на серверной стороне должна поддерживаться возможность выполнения криптографических преобразований по ГОСТ Р 34.10-2001, ГОСТ Р 34.11-94 и SHA-1.

Доработка кода серверной части включает в себя следующие этапы:

  • Генерация идентификатора журнала операций.
  • Идентификация терминала по серийному номеру из журнала операций.
  • Аутентификация терминала.
  • Проверка совпадения фактически отображённых на терминале данных и данных, которые должны были быть отображены в соответствии с настройками.
  • Сохранение журнала операций в базе данных для формирования доказательной базы.
  • (Опционально) Проверка привязки данного Антифрод-терминала к учетной записи данного пользователя (что он был выдан именно ему).

Генерация идентификатора журнала операций

Генерация идентификатора журнала операций на серверной стороне нужна для защиты от попыток вредоносного ПО повторно навязать серверу перехваченный ранее в канале связи или на ПК пользователя журнал операций. Идентификатор состоит из 8 байт и нужен для привязки журнала к конкретной операции подписания документа или операции безопасной аутентификации. Идентификатор должен:

  • либо генерироваться случайным образом;
  • либо в качестве него должен выступать уникальный идентификатор документа (например, сохранённого на сервере платёжного поручения, ожидающего подписание). В этом случае журнал будет привязан к конкретному платёжному поручению по этому идентификатору и вредоносное ПО не сможет повторно навязать серверу этот журнал с копией такого же платёжного поручения.

Идентификатор должен передаваться клиентской стороне. Клиентская сторона поместит его в журнал операций в поле Reference при старте SWYX-режима работы с Антифрод-терминала.

Идентификация терминала по серийному номеру из журнала операций

Для идентификации терминала необходимо:

  1. Извлечь серийный номер Антифрод-терминала из поля журнала с тегом ReaderSerialNr.
  2. Найти в базе данных зарегистрированный Антифрод-терминал с этим серийным номером.

Необходимо учесть, что серийный номер в журнале операций дополнен слева фиктивными нулями до последовательности из 16 цифр.

Аутентификация терминала

Для аутентификации терминала необходимо:

  1. Найти в базе данных значение открытого ключа идентифицированного Антифрод-терминала.
  2. Проверить подпись журнала с помощью этого ключа. Пример исходного кода можно получить по ссылке.
  3. Проверить соответствие идентификатора из журнала операций (поле Reference) тому значению, которое на первом этапе было отправлено сервером клиентской стороне в качестве идентификатора журнала операций.

При неуспешной аутентификации операция должна быть заблокирована.

Проверка совпадения фактически отображённых на терминале данных и данных, которые должны были быть отображены в соответствии с настройками

Проверка соответствия позволяет проверить, что:

  • терминал отобразил на своем экране определенный текст (например, ключевые реквизиты подписанного платёжного поручения);
  • пользователь пролистал этот текст до конца на терминале;
  • пользователь подтвердил свое намерение выполнить операцию подписания (или безопасную аутентификацию) в соответствии с отображённым на экране терминала данными.

Для проверки соответствия прикладная программа на сервере должна выполнить следующую последовательность действий:

  1. Сформировать текст, который должен был быть отображён на экране терминала. Сервер должен знать, как сформировать этот текст, так как он формировался прикладной программой в соответствии с заданными на сервере настройками.

  2. Сформировать на основе этого текста специальную структуру SWYX_DISPLAY_COMMAND.

    Структура SWYX_DISPLAY_COMMAND имеет следующий вид:

    {
      BYTE bSwyxFunction;
      BYTE bTimeout;
      USHORT wLangId;
      USHORT wLength;
      BYTE abB64UTF8[];
      BYTE bDisplayIndex;
    }
    

    В каждой такой структуре:

    • bSwyxFunction – байт, принимающий значение 0x02.
    • bTimeout – время ожидания терминалом нажатия пользователем кнопки OK или C, выраженное однобайтовым числом 5-секундных интервалов (в случае бесконечного времени ожидания bTimeout=0x00).
    • wLangId – двухбайтовый идентификатор языка (например, для русского языка wLangId = 0x0419) в представлении от младшего к старшему (little-endian).
    • wLength – длина массива abB64UTF8[] в байтах, выраженная в представлении от младшего к старшему (little-endian).
    • abB64UTF8[] – байтовый массив, представляющий собой отображённый на экране Антифрод-терминала текст, переведённый из кодировки UTF-8 в кодировку Base64.
    • bDisplayIndex – параметр для отображения текста: 1 - “Подписать = OK” или 0 - “Подтвердить = OK”.

    Примечание

    для команды aftSwyxDisplay устаревшего формата (без аргумента extensions) параметр bDisplayIndex не используется и добавлять его в структуру для проверки не требуется.

  3. Вычислить от структуры SWYX_DISPLAY_COMMAND хеш по SHA-1 с использованием сторонней библиотеки, подходящей для используемого языка программирования.

  4. Представить полученный хеш в кодировке Base64.

  5. Извлечь из журнала операций значение SecureLog 02.

  6. Сравнить посчитанный хеш со значением SecureLog 02.

    • Если они не совпадают – значит, документ поддельный (искаженный). И сервер отказывает в принятии его на исполнение.

    • Если совпадают – значит содержимое подписанного документа (или его ключевые данные) было действительно отображено на экране терминала, просмотрено пользователем до конца и подтверждено им на клавиатуре терминала.

      <?php
      public function checkSwyxLog($log, $displayText, $logSign, $timeout)
      {
         $log = base64_decode($log); // журнал операций терминала
         $parser = new SimpleXMLElement($log);
      
         // Извлекаем из структуры XML документа значение SecureLog id=”02”
         $swyxSecureLog = $parser->SecureLogs->SecureLog[1];
         $textArray = array();
      
         $decodedText = base64_encode($displayText);
         $length = strlen($decodedText);
         $textArray[] = 0x02;
         $textArray[] = (int)$timeout;
         $textArray[] = 0x0419 & 0xFF;
         $textArray[] = (0x0419 >> 8) & 0xFF;
         $textArray[] = $length & 0xFF;
         $textArray[] = ($length >> 8) & 0xFF;
         If($MessageIndex == 0x00) $textArray[] = 0x00
         else
         $textArray[] = 0x01;
         foreach (unpack('C*', $text) as $c){
            $textArray[] = $c;
      
         //Конвертируем массив символов в строку для хеширования
         $textToCheck = implode('', array_map('chr', $textArray));
         //Хешируем SHA-1 и преобразуем полученные бинарные данные и Base64
         $textHash = base64_encode(sha1($textToCheck, true));
         return ($swyxSecureLog == $textHash);
      }
      ?>
      

      Примечание

      В случае, если в SWYX-режиме на Антифрод-терминал выводился не один текст, а несколько последовательно, при анализе журнала операций необходимо сформировать структуры SWYX_DISPLAY_COMMAND для каждого такого текста и вычислить хеш по SHA-1 от последовательности этих структур в порядке вывода соответствующих им текстов на экран терминала.

      <?php
      public function checkSwyxLog($log, array $displayText, $logSign, $timeout)
      {
         $log = base64_decode($log); // журнал операций терминала
         $parser = new SimpleXMLElement($log);
      
         // Извлекаем из структуры XML документа значение SecureLog id=”02”
         $swyxSecureLog = $parser->SecureLogs->SecureLog[1];
         $textArray = array();
      
         //Склеиваем массив сообщений, отображенных на экране терминала
                 //и подтвержденных пользователем в SWYX-режиме работы терминала,
                 //в единый текст
         foreach ($displayText as $p) {
            $text = base64_encode($p);
            $length = strlen($text);
            $textArray[] = 0x02;
            $textArray[] = (int)$timeout;
            $textArray[] = 0x0419 & 0xFF;
            $textArray[] = (0x0419 >> 8) & 0xFF;
            $textArray[] = $length & 0xFF;
            $textArray[] = ($length >> 8) & 0xFF;
                If($MessageIndex == 0x00) $textArray[] = 0x00
            else
               $textArray[] = 0x01;
            foreach (unpack('C*', $text) as $c){
               $textArray[] = $c;
            }
      
         //Конвертируем массив символов в строку для хеширования
         $textToCheck = implode('', array_map('chr', $textArray));
         //Хешируем SHA-1 и преобразуем полученные бинарные данные и Base64
         $textHash = base64_encode(sha1($textToCheck, true));
         return ($swyxSecureLog == $textHash);
      }
      ?>
      

Сохранение журнала операций в базе данных для формирования доказательной базы

Независимо от результата проверки журнала операций сохранить его в базе данных в целях ведения доказательной базы для возможности разбора конфликтных ситуаций и расследования инцидентов.

(Опционально) Проверка привязки данного Антифрод-терминала к учетной записи данного пользователя (что он был выдан именно ему)

Можно при необходимости провести дополнительную проверку, был ли этот терминал выдан конкретно этому пользователю. Реализуется на уровне бизнес-логики.

Оглавление