О чем это


На идею создать свой маленький интернет-проект по защите документов от подделки, меня натолкнула дискуссия на форуме дефектоскопистов, посвященная повальной подделке выданных ими заключений по контролю качества.

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

Актуальность задачи защиты от подделок


Дело в том, что в наш век безбумажной информации ни одно капитальное строительство, будь то газопровод или торговый центр, не обходится без подготовки полного комплекта исполнительной документации (as built), частью которой являются заключения по неразрушающему контролю (визуальному, радиографическому, ультразвуковому).



Это заключение — оформленный на определенном бланке документ с выводом о годности или негодности, к примеру, сварного шва. Услуги по неразрушающему контролю стоят денег и часто весьма немалых. Недобросовестный заказчик/посредник может нанять аккредитованную лабораторию, получить от нее несколько заключений и прекратить или приостановить работу.

Каково же может быть удивление дефектоскописта или начальника лаборатории, когда они узнают о том, что и после прекращения работы от их имени выдаются заключения, на них ставятся поддельные печати и подделываются подписи. Страдает репутация лаборатории, да и по сути нарушается законодательство. Просто в ряде случае об этом так никто и не узнает.

В рамках дискуссии — как защитить свои документы, была высказана идея наносить на документ QR-код, в котором будет записан номер заключения, дата и вывод о годности или не годности объекта контроля. Чем хорош такой способ — QR-код останется хорошо различим при сканировании, копировании документа.

Однако, просто сгенерировать QR-код с нужным содержимым точно также смогут и мошенники.

Рождение идеи


И тут меня осенила мысль — а почему бы не шифровать содержимое такого QR-кода надежным алгоритмом. Раз так — надо придумать способ его расшифровывать при сканировании, например через камеру смартфона. Здесь родилась идея расшифровку делать на стороне web-сервиса, который будет хранить ключ для расшифровки.

В последний раз я делал сайт в 2000 году в notepad и не слишком хорошо знаком с современными технологиями сайтостроительства, поэтому выбрал Wix, подумав, что с помощью сервиса я получу красивую картинку и минимальные возможности работы с базой данных, а с помощью Wix code закодирую то что мне нужно.

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

Шифрование


Готовый алгоритм AES 128-битного шифрования с реализацией на Java Script я взял на Github и разместил в backend разделе сайта.

Это была, пожалуй, самая простая часть работы. Как работает само шифрование мне было не совсем неинтересно. Меня волновала грандиозность задуманного.

Главное не забыть перевести кодируемый текст в Bytes, а результат шифрования в HEX.

// Convert text to bytes
var textBytes = aesjs.utils.utf8.toBytes(text);

// The counter is optional, and if omitted will begin at 1
var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));

var encryptedBytes = aesCtr.encrypt(textBytes);

// To print or store the binary data, you may convert it to hex
var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);

Генерация QR-кода


Я воспользовался готовым API.

Для работы достаточно создать объект html1 — для отображения произвольного html кода и вызвать фунцию API

let val = “Шифруемый текст"
$w("#html1").src = "https://api.qrserver.com/v1/create-qr-code/?size=100x100&data=" + val.toString();
$w("#html1").show();

Работа с пользователями


Wix поддерживает базовые функции регистрации пользователей и редактирования профиля. Инструмент, несколько глючный, но работоспособный.

Мне лишь потребовалось добавить поле, которое описывает наименование организации, которую представляет зарегистрированный пользователь, но это поле read only и его заполняет администратор сервиса, когда получает подтверждение, что зарегистрированный пользователь действительно представляет указанную организацию.

Потребовалось также прикрутить простейшую логику, связанную с платным/бесплатным доступом к функциям (до 20 документов в месяц можно защитить бесплатно) и сроком оплаты услуг.

Принцип работы


К аккаунту пользователя привязывается уникальный закрытый ключ шифрования.

Залогиненый пользователь заполняет форму с информацией о заключении (номер, дата, результат):



Затем алгоритм выдает URL, содержащий зашифрованный текст TEXT и, выступающий в виде открытого ключа USER_ID, как на примере ниже:

https://*имя сервиса*/checkqr?user=3b01b0aa-68a0-4521-ab12-f17b86d3eabc&v=1.0&text=8a026594c26be959f4280e28fe8402c1acef233e369a31613d654d3b0a5bbaca206f3058d27d2fde66b65cb64a5a6caecb69b07ad39c0015e923dad89eb723

URL превращается в QR-код, который пользователь уже наносит на свой документ, скопировав в буфер обмена (можно включить в исходный файл или же налепить как стикер на готовый напечатанный документ).



Что здесь важно — как таковая информация не попадает в базу данных сайта, а остается лишь в виде этой ссылки и QR-кода, содержащего эту ссылку. Таким образом, никакая информация о содержимом защищаемого документа на сервере не хранится.

Проверка кода выполняется сайтом при распарсивании ссылки


Для распарсивания при распознавании сайтом ссылки я воспользовался справкой по Wix code
www.wix.com/code/reference/wix-http-functions.html

Если при расшифровке что-то пошло не так, а это может быть, если в оригинальный QR-код попытались внести какие-то изменения
«Код документа расшифрован с ошибкой. Возможна подделка. Обратитесь в организацию, подготовившую документ для получения пояснений»
Если расшифровка завершена успешно, то выдается расшифрованный текст, содержащий название лаборатории, номер документа, дату выдачи и результат, а пользователю предлагается сопоставить результат расшифровки с тем, что он видит на реальном документе.

Заключение


От рождения идеи я с помощью ряда готовых кирпичиков пришел к работающей реализации.

Приглашаю к дискуссии по придуманной мной идее, попытке протестировать/взломать мой сервис.

Что еще осталось доделать


  • Написать по итогам реализации на habr
  • Разобраться как сбросить query, если один раз уже была проверка ссылки
  • Придумать как ужать зашифрованный текст, потому что когда длинный URL кодируется, то размер QR-кода чересчур большой
  • Добавить возможность копирования кода в буфер обмена или отправлять на почту по щелчку на кнопку (пока не разобрался как сделать это в javascript)
  • Улучшить работу с мобильной версией

Предварительный ответ на возможную критику:


Не проще лаборатории вести реестр заключений на своем сайте, а подобная QR метка будет вести на этот реестр или даже выводить копию заключения?
Это можно сделать, но потребуется значительная ручная работа или внедрение собственного IT решение наподобие разработанного мной, но это явно обойдется дороже чем воспользоваться готовым решением.

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

Комментарии (32)


  1. technomancer
    01.03.2019 12:23

    А что помешает недобросовестному лицу сделать QR-код со ссылкой на свой сайт, где будет написано «Всё честное и настоящее, мамой клянусь, вах!»? Без доверенных и всем известных центров (хотя бы тот же Ростехнадзор) полезный эффект будет небольшой. Разве что лаборатория заведет себе сайт. Но и этот факт (и этот сайт) должен быть широко известен.


    1. bazin Автор
      01.03.2019 12:54

      Именно для этого я и придумал свой сервис, который может стать тем ресурсом, которому можно доверять.
      А, действительно, если мошенник захочет — он может измахриться и сделать копию моего сайта, на котором будет подтверждать подлинность документов. Тогда в QR-код я буду добавлять название веб-сайта.

      Хотя, конечно, в этом есть истина, лучше сервис раскрутить и продать Ростехнадзору.


      1. OneType
        01.03.2019 14:35

        То есть вы хотите сказать, что вам можно доверять?


        1. bazin Автор
          01.03.2019 15:01

          Хороший вопрос. Сервис, конечно, может быть скомпрометирован.
          Но задуман он именно как решение, которому можно доверять больше чем варианту с печатями, подделать которые стоит не дороже 1000 рублей.


      1. ProstoUser
        01.03.2019 14:36

        Не получится продать. Как только появляется шифрование, да еще и упоминаются госорганы, сразу встает вопрос о лицензии и сертификации ФСБ. Это продать не получится никак. Разве что в качестве идеи для реализации лицензированной компанией.


  1. wtigga
    01.03.2019 12:44

    У китайской налоговой документы работают примерно так. В левой верхней части есть здоровенный QR-код, который ведёт на сайт в домене *.gov, где лежит электронная версия этого же самого документа. И на сайте налоговой можно точно так же вбить номер документа и проверить его содержимое.

    В целом, ничто не мешает написать приложение, которое будет игнорировать ссылки за пределами домена в зоне *.gov.


  1. serf
    01.03.2019 13:12

    Почему без соли шифруете?


    1. bazin Автор
      01.03.2019 13:22

      Спасибо за комментарий. В тонкостях работы алгоритмов шифрования пока не разобрался.
      Вы полагаете, что недостаточно иметь 128-битный ключ?


      1. serf
        01.03.2019 13:26

        Ключ это несолько другое, хотя если нет технических ограничений можно взять 256. У используемой библиотеки github.com/ricmoo/aes-js прямо в ридми есть пример шифрования с использованием initialization vector, например CBC вариант.


      1. andreymal
        01.03.2019 13:40
        +1

        В тонкостях работы алгоритмов шифрования пока не разобрался.

        Вы опасно некомпетентны в криптографии


        Там не про AES, но всё равно. Если вы не в курсе про соль (и про CBC), то вы явно опасно некомпетентны


        1. bazin Автор
          01.03.2019 14:45

          Некомпетентен, не спорю. Спасибо за ссылку!


        1. bazin Автор
          02.03.2019 16:28

          Прочитал статью. В целом ощущение, что товарищ защищает свою делянку профессионала и правильно делает.

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

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

          Когда я выбирал алгоритм для шифрования, залез почитал про AES (не то как он работает — мне это было не важно), а то что он рекомендован правительством США для документов уровня SECRET с ключом 128.

          Я даже исхитрился и сделал так, что сам ключ в базе данных не хранится. Украсть его не получится.

          Ниже товарищи указали, что следовало бы воспользоваться асимметричным шифрованием, возможно это разумно. Но вместе с тем, мое решение работоспособно и пока я не увидел принципиального изъяна кроме самого сомнения в том, что сервис действительно предоставляется не надежным с административной точки зрения. Тут уж надо, видимо переходить на blockchain, но это будет уже выходить за пределы любительского pet-проекта.


    1. Inanity
      01.03.2019 13:43

      Да даже если с солью и перцем шифровать — общая схема неверна. Соль нужна для хэша, а не симметричного алгоритма.


      1. serf
        01.03.2019 13:57

        Имелось ввиду использование рандомного initialization vector. Об общей схеме речи не было.


        1. Inanity
          01.03.2019 14:02

          Ок, но тогда ошибка в терминологии. Initialization Vector — это не соль. IV обязан храниться в секрете (UPD: на самом деле нет, ошибся), в то время как соль хэша можно хранить в открытом виде.


          1. serf
            01.03.2019 14:06

            Каюсь что статью не читал, только код посмотрел и сразу комментировать, как обычно.

            IV обязан храниться в секрете, в то время как соль хэша можно хранить в открытом виде, это не секрет.
            Мне казалось что IV не должен повторятся при использовании того же самого ключа (рандом), а хранение в секрете желательно, также как и для key derivation хешей, но не обязательно.


            1. Inanity
              01.03.2019 14:09

              Согласен, ошибся. IV тоже не секрет, может передаваться в открытом виде.


  1. ultrinfaern
    01.03.2019 13:40

    Вам нужно почитать про криптографию с открытым/закрытым ключём.
    Создаём qr код с ОТКРЫТЫМ текстом и его подписью закрытым ключём. Для проверки нужен всего лишь открытый ключ, ну и открытая база открытых ключей организаций, которым вы доверяете.


    1. bazin Автор
      01.03.2019 14:43

      Спасибо, я понял!

      А можно ли добавить открытый ключ в ту же зашифрованую гиперссылку?
      Тогда она будет выглядеть как ОТКРЫТЫЙ_ТЕКСТ&ПОДПИСЬ&ОТКРЫТЫЙ_КЛЮЧ и мой сервис просто верифицирует подпись.

      К счастью я сразу предусмотрел в формируемой ссылке поле version. В версии 2.0 учту.


      1. ultrinfaern
        01.03.2019 15:50

        Вы правы, чтобы проверить подпись нужно знать кто подписал. Но все равно вам нужна отдельно база тех, кому вы доверяете. Иначе плохая организация может сгенерировать открытый ключ и валидную подпись, но так как этого сгенерировано ключа нет в вашей базе, то он фейковый.
        Об этом можно почитать — инфраструктура открытых ключей PKI.


        1. bazin Автор
          02.03.2019 16:49

          Спасибо, почитал.

          Теперь мне стало ясно что такое по сути ЭЦП.

          Получается что все-равно нужен кто-то кому все доверяют. Тогда придется брать на себя роль УЦ, а это уже регулируется законодательством.

          Но в то же время я думаю вот о чем — о практике применения. Если все сделать по принципу ЭЦП, то представитель лаборатории может продать/передать/потерять закрытый ключ и его работодатель об этом не узнает.
          Представьте себе к, примеру, организацию которая выписывает медицинские справки. Ясное дело, что у того, кто имеет доступ к ключу есть искушение начать работать «налево».

          Да, он точно также может и продать/передать/потерять доступ к личному кабинету на моем сайте, где хранится ключ и тогда левые организации или он сам смогут подписывать фейковые документы.
          Для этого у меня ведется учет сгенерированных документов. Пока просто по количеству. Соответственно, если количество защищенных документов не будет сходиться с количеством официально выпущенных, значит что-то пошло не так и об этом будет известно при ежемесячном отчете.


  1. Inanity
    01.03.2019 13:41

    1. Вы в корне неправильно применяете криптографические примитивы. Вам не нужно шифровать информацию симметричным алгоритмом (AES128), т.е. скрывать содержимое от третьих лиц, ведь результаты дефектоскопии прописаны в бланке в открытом виде и ни для кого секрета не представляют. Вам необходимо именно аутентифицировать содержимое бланка, т.е. гарантировать обнаружение подделки. Для этого применяются совсем другие средства.

    2.

    К аккаунту пользователя привязывается уникальный закрытый ключ шифрования.
    Если я правильно понял, то вы на сервере храните симметричные ключи от всех аккаунтов, что очень плохо, т.к. их могут украсть. Таким образом я, как пользователь сервиса никогда не смогу узнать, что ключ был продан, а все мои новые бланки с какого-то момента подделаны. Но это уже следствие первой проблемы.


    1. bazin Автор
      01.03.2019 16:04

      Спасибо, за комментарий. Я рассчитывал что профессиональное сообщество укажет мне на мои ошибки.

      К счастью я сразу предусмотрел в формируемой ссылке поле version. В версии 2.0 учту что подход должен быть с открытым/закрытым ключом.

      Кстати, я не храню сам ключ в базе данных. Для передачи в алгоритм шифрования то что хранится в базе данных определенным образом дополнительно преобразовывается. То есть надо не только украсть сам «ключ» но и найти тот код, который трансформирует его.


      1. ProstoUser
        04.03.2019 10:43
        +1

        Для передачи в алгоритм шифрования то что хранится в базе данных определенным образом дополнительно преобразовывается. То есть надо не только украсть сам «ключ» но и найти тот код, который трансформирует его.


        Это называется «Security through obscurity» — безопасность достигается путем секретного алгоритма. В современно мире считается, что на подобных принципах стоить безопасность недопустимо. Весь анализ возможных атак всегда строится в предположении, что все алгоритмы есть в распоряжении взломщика. Причем, не только обфусцированный код, а полная документация с указанием того, что, зачем и почему именно так там делается.


  1. xFFFF
    01.03.2019 14:23
    +1

    Мне кажется, что у злоумышленников есть все возможности подобрать симметричный ключ перебором.


  1. mwambanatanga
    02.03.2019 08:04

    Зачем? Можно просто сделать доступными электронные версии выдаваемых вами документов, а в сами документы вставлять ссылку (QR-код или URL) на электронную версию. Есть на сайте — значит, действительно вы выдали. Нет на сайте — значит, вы такого не выдавали.


    1. bazin Автор
      02.03.2019 10:32

      Можно, и это вполне реальное решение для той организации, которая выдает документы. Но для этого нужно каждому городить свое собственное решение, делать портал на который будут скидываться документы из ряда лабораторий, работающих на местах, короче некое инфрастуктурное IT решение, до которого у большинства просто руки не доходят.

      А моя идея состоит в том, чтобы предоставить такой сервис любой компании — маленькой и большой, но при этом сами данные не хранятся у меня, хранятся только ключи к расшифровке.


      1. RouR
        03.03.2019 16:48

        Самое простое решение — выкладывать по ссылке site.com/22345200-abe8-4f60-90c8-0d43c5f6c0f6/10465677-c121-99j0-1111-22187a169871/act.pdf
        Саму ссылку зашивайте в QR-код. Защита основана на сложности перебора длинных путей и отсутствия единого публичного списка всех ссылок.
        Выложить файл на сайте — что может быть проще.
        Вы жалуетесь что для этого надо городить своё решение, но при этом, вас почему-то устраивает необходимость создания своего решения в виде мобильного приложения.


        1. mwambanatanga
          04.03.2019 07:09

          Опять же, зачем защита от перебора? Документ в принципе не является секретным. Более того, желательно предусмотреть возможность доступа к электроному документу без QR-кода (например, нужен дубликат в случае утери оригинала с QR-кодом).


          1. RouR
            04.03.2019 10:20

            Затем что цитата из статьи —

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


            1. mwambanatanga
              04.03.2019 12:04

              Упс, виноват. Если моё решение задачи не подходит, значит это неправильная задача это решение от другой задачи.


        1. andreymal
          04.03.2019 11:32
          +1

          На всякий случай отмечу, что для таких файлов ещё следует добавить HTTP-заголовок X-Robots-Tag: noindex, а то уже бывали случаи, когда документы случайно утекали гуглу с яндексом