Как я решил защищать документы от подделки и «изобрел» электронную цифровую подпись

О чем это


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

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

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


Дело в том, что в наш век безбумажной информации ни одно капитальное строительство, будь то газопровод или торговый центр, не обходится без подготовки полного комплекта исполнительной документации (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 решение наподобие разработанного мной, но это явно обойдется дороже чем воспользоваться готовым решением.

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

Подробнее
Реклама

Комментарии 33

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

      Хотя, конечно, в этом есть истина, лучше сервис раскрутить и продать Ростехнадзору.
        0
        То есть вы хотите сказать, что вам можно доверять?
          +1
          Хороший вопрос. Сервис, конечно, может быть скомпрометирован.
          Но задуман он именно как решение, которому можно доверять больше чем варианту с печатями, подделать которые стоит не дороже 1000 рублей.
          0
          Не получится продать. Как только появляется шифрование, да еще и упоминаются госорганы, сразу встает вопрос о лицензии и сертификации ФСБ. Это продать не получится никак. Разве что в качестве идеи для реализации лицензированной компанией.
        0
        У китайской налоговой документы работают примерно так. В левой верхней части есть здоровенный QR-код, который ведёт на сайт в домене *.gov, где лежит электронная версия этого же самого документа. И на сайте налоговой можно точно так же вбить номер документа и проверить его содержимое.

        В целом, ничто не мешает написать приложение, которое будет игнорировать ссылки за пределами домена в зоне *.gov.
          –1
          Почему без соли шифруете?
            –1
            Спасибо за комментарий. В тонкостях работы алгоритмов шифрования пока не разобрался.
            Вы полагаете, что недостаточно иметь 128-битный ключ?
              –1
              Ключ это несолько другое, хотя если нет технических ограничений можно взять 256. У используемой библиотеки github.com/ricmoo/aes-js прямо в ридми есть пример шифрования с использованием initialization vector, например CBC вариант.
                +3
                В тонкостях работы алгоритмов шифрования пока не разобрался.

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


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

                  0
                  Некомпетентен, не спорю. Спасибо за ссылку!
                    +1
                    Прочитал статью. В целом ощущение, что товарищ защищает свою делянку профессионала и правильно делает.

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

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

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

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

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

                  0
                  Да даже если с солью и перцем шифровать — общая схема неверна. Соль нужна для хэша, а не симметричного алгоритма.
                    0
                    Имелось ввиду использование рандомного initialization vector. Об общей схеме речи не было.
                      0
                      Ок, но тогда ошибка в терминологии. Initialization Vector — это не соль. IV обязан храниться в секрете (UPD: на самом деле нет, ошибся), в то время как соль хэша можно хранить в открытом виде.
                        0
                        Каюсь что статью не читал, только код посмотрел и сразу комментировать, как обычно.

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

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

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

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

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

                      0

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

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

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

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

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

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

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

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

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


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

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

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

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

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

                            0
                            Конечно, проще всего было бы забивать номер документа на сайте (или кодировать ссылку с этим номером), и сайт бы показывал какие-то ключевые данные о документе. Но, если информация секретная (даже не представляю причин, почему она может быть секретной, но это наше общее тяжелое наследие), то тогда только и остается генерировать гигантские QR-картинки. Можно попробовать переводить в собственный алфавит, который из 5-6 бит, а значит немного ужать количество информации. Или даже даже сделать свою вариацию хаффмана с известной таблицей кодирования/декодирования — можно будет еще немного ужать.

                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                            Самое читаемое