Воплощение идеи Bitcoin для борьбы со спамом

в 9:54, , рубрики: bitcoin, captcha, javascript, Веб-разработка, интерфейсы, метки: , ,

Суть решения

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

Пример использования

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

Идея

Применить некоторую ассиметричную операцию, которая будет затратной по ресурсам для клиента и легковесна для проверки с серверной стороны. Другими словами отправка формы должна стать достаточно ресурсоёмкой операцией. Так как с точки зрения обычного польователя «повисание» браузера на 1-3 минуты является не приятной, но вполне приемлемой особенностью работы сайта, а вот для спам бота, если каждай отсылаемая форма будет «съедать» 1-3минуты 100% заргузки одного ядра процессора будет крайне неприятным сюрпризом. Также это позволит бороться со случаями, если спам рассылается именно людьми: т.е. когда и браузер настоящий и есть человек за браузером.

Причем тут Bitcoin?

Из Bitcoin взята идея Proof of work. Другими словами клиентскому браузеру нужно решить головоломку соответствющей сложности, как это делается Bitcoin майнерами: вычислить nonce + hash для некоторого поля формы, причем hash должен отвечать некоторому критерию. Операцию можно решить только перебором, который потребует существенных вычислительных ресурсов для клиента. При этом вычисленное значенеи hash + nonce можно легко проверить на сервере.

JavaScript код на стороне клиента

var isBrowserJsRuntime = (typeof exports === 'undefined');
var nonce;
if(isBrowserJsRuntime){
    nonce = this['nonce']={};
} else {
    jsSHA = require('./sha512');
    nonce = exports;
};
nonce.nonce = function(inString){
    var btc = "";
    var j = 0;
    var n = 0;
    for( ; btc.search('123456') < 0 ; j++ ){
        btc = ((new jsSHA( inString + j, 'TEXT')).getHash('SHA-512', 'HEX'));
        n = j;
    };
    return { 'btc':btc, 'nonce':n };
};

nonce.pushButton = function(thisForm){
    var fullMsg = thisForm.message.value;
    var n = this.nonce(fullMsg);
    thisForm.btc.value = n.btc;
    thisForm.nonce.value = n.nonce;
    thisForm.submit();
};

Дополнительно потреюуется любая JavaScript библиотека вычисляющая любой (ресусоёмкий) hash. Например, отлично подойдет jsSHA, в частности sha512.js

Код работает на node.js (для Unit тестирования) и в браузере Cromium. В качестве критерия подходящего hash применяется последовательность 123456. То есть nonce будет подобран таким образом, чтобы вычисленный hash содержал последовательность '123456'.

Perl код на стороне сервера

use Digest::SHA qw(sha512_hex);

sub checkProofOfWork($$$){
    my $text = shift;
    my $nonce = shift;
    my $shaValue = shift;
    if( $shaValue =~ /123456/ ){
        my $digest = sha512_hex( $text . $nonce );
        return $digest eq $shaValue;
    };
    return 0;
};

Cначала проверяем, что вычисленный hash подходит по критерию и только потом пытаемся пересчитать hash сами.

Заключение

Массовое применение подобного подхода способно существенно усложнить жизнь спамерам.
Также мне интересно мнение сообщества в отношении предложенного подхода и пути его дальнейшего совершенствования.

Автор: AxVPast

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js