Несмотря на бурное развитие технологий, по сегодняшний день многие разработчики гнушаются локальным хранением элементарной информации: используют Google fonts, загружают килобайтный JS-файл с сервера, расположенного на другом континенте и прочие топологические и логические неоднозначности. При таком подходе к разработке веб-приложений мысли о локально-генерируемой и этичной капче появляются крайне редко. А если и появляются, возникают вопросы: как генерировать, хранить и проверять ответы, ассоциировать картинки с конкретной сессией пользователя и прочее. Итог почти всегда один: использовать сторонние онлайн-сервисы вроде reCAPTCHA. На вкус и цвет товарищи всегда найдутся, но сейчас рассмотрим альтернативу.
Давайте познакомимся с Zero Storage Captcha, которая работает локально (возможно, в виде дополнительного класса в коде приложения), не обязывает хранить информацию на стороне сервера о сгенерированных картинках и в тот же момент позволяет проверить ответ любого пользователя со стопроцентной вероятностью.
Концепция
Если не хочется организовывать базу данных под капчи, почему бы не хранить ответ на капчу у самого пользователя? Чтобы реализовать эту идею и при этом исключить перехват ответа на картинку на стороне пользователя, нужно обратиться к базовой криптографии. Пусть пользователь хранит не ответ в чистом виде, а специальный токен, который будет передан серверу вместе с ответом на капчу и позволит проверить правильность ответа. Криптография поможет нам не хранить пару "правильный ответ - токен", а производить проверку через простые вычисления по факту поступления запроса от пользователя.
Встает несколько вопросов:
Алгоритм генерации токена, защищенный от подделки;
Ограничение времени жизни капчи;
Невозможность использования одного верного ответа дважды.
Реализация
Опустим детали того как генерируется изображение. В эталонной реализации отрисовка происходит графическими силами фреймворка Qt/C++, но это не принципиально и вполне возможны другие решения.
Итак, при получении капчи, которую пользователю следует разгадать, он получает изображение и проверочный токен. Затем на сервер отправляются ответ пользователя и тот самый токен, благодаря которому происходит проверка правильности введенных данных.
Токен базируется на следующих составляющих:
Верный ответ на капчу;
Хеш (SHA256);
Подпись (X25519);
Временной маркер.
В виде формулы алгоритм создания токена можно представить так:
SIGNATURE( HASH(answer value + time token) )
Фактически токен является подписью в кодировке base64. Чтобы сделать токен более компактным, принято решение сокращать подпись в три раза — в итоговую строку добавляется каждый третий символ. Также удаляются все спецсимволы вроде =
, -
и _
. На выходе получается строка примерно такого вида: i2oefBw6mswaORIphgDcY7GwnS
.
Временной маркер (time token) обновляется каждые полторы минуты, благодаря чему через небольшой промежуток времени проверочный токен для капчи с тем же ответом будет абсолютно новый.
Логика построена таким образом, чтобы одновременно хранились два тайм-токена: актуальный и предыдущий. Это необходимо для нормальной проверки капчи, которая была сгенерирована за несколько секунд до смены тайм-токена. Если проверка ответа с актуальным тайм-токеном выдает false
, происходит проверка с предыдущим. Учитывая эту специфику, несложно подсчитать примерное время жизни сгенерированной капчи: от полутора до трех минут.
Фактором уникальности проверочных токенов также является сессионный ключ подписи, который генерируется при каждом запуске приложения (вернее, при первом обращении к классу, отвечающему за генерацию капчи).
Можно усомниться в нужности хеша, так как операция подписи даст не менее уникальную строку при прямом применении к сконкатенированной строке answer + time token
. С этим сложно поспорить, поэтому оправдывать хеш сильно не стану: в изначальной реализации он есть и хлеб не просит. Возможно, в будущих реализация Zero Storage Captcha произойдет отказ от предварительного хеширования.
Получая от пользователя токен и ответ на капчу, сервер выводит из ответа пользователя новый токен. Если новый токен и изначальный проверочный совпадают, о верности ответа выносится положительный вердикт.
Чтобы верным ответом нельзя было воспользоваться более одного раза, после успешного прохождения проверки проверочный токен заносится в специальный кеш, где хранится в течение короткого жизненного цикла капчи (до трех минут). Если на проверку поступит токен, имеющийся в кеше использованных токенов, ответ сервера будет отрицательным.
Использование
Сфера применения описанной технологии также широка, как и область применения любой капчи. В сценарии с веб-страницами Zero Storage Captcha может быть реализована при помощи JS, либо силами чистого HTML, если он генерируется на бекэнде и позволяет подставлять дополнительный уникальный ключ в <form>
отправки ответа на капчу.
Если вы хотите использовать Zero Storage Captcha в проектах на C++, ознакомьтесь с заголовочной библиотекой на несколько сотен строк. Если интеграция плюсового класса в ваш продукт затруднительна, воспользуйтесь Zero Storage Captcha в виде отдельного приложения, которое предоставляет простой REST API и может работать как локально, так и на любом удобном для вас сервере.