VKScript – это JavaScript-подобный язык, совершенно урезанный, поддерживающий лишь несколько конструкций и операторов. Он выполняется на стороне ВКонтакте, и его код можно хранить в настройках приложения, делая его скрытым от пользователей.
Мне нужно защитить от подделок некий параметр, передаваемый с моего сервера, в браузер посетителей, и оттуда – в вызов методов ВК api.
План простой: на сервере считать хэш от этого параметра, секрета и id пользователя, который нельзя подделать при обращении к api ВКонтакте. А в коде процедуры execute проверять эту подпись. Всё бы хорошо, но md5() в VkScript, наверное, не реализовать из-за ограничений языка, числа повторов в циклах и т.п.
Подскажите хэш-функцию, пусть, не достаточно безопасную для банков, но и не примитивно взламываемую школьниками – которую можно реализовать в рамках VKScript.
VkScript поддерживает только вот такие вещи:
арифметические операции
логические операции
создание массивов и списков ([X,Y])
parseInt и parseDouble
конкатенация (+)
конструкция if
фильтр массива по параметру (@.)
вызовы методов API, параметр length
циклы, используя оператор while
методы Javascript: slice, push, pop, shift, unshift, splice, substr
оператор delete
присваивания элементам маcсива, например: row.user.action = "test";
Из битовых операций поддерживаются только &, |, ~, << и >>. А вот XOR'а ^, который бы очень помог, нет. Также ограничены кол-во повторов в циклах и общее время выполнения – сложные алгоритмы не реализовать.
Upd. XOR, как мне подсказали, реализуется: a xor b == (a|b)&~(a&b), так же, как и сдвиг с заполнением: a >>> b == (a >> b) & (a<<(32 - b)), при условии b < 32.
Ответ
Собственно, всё решилось хешем Дженкинса примерно в такой реализации. Код хранимой процедуры ВК:
var secret = 123456
,uid = API.users.get()[0].id
,param = parseInt(Args.param)
,signature = parseInt(Args.signature)
,toCrypt = [ param, uid, secret]
,b
,hash = 0
;
while( toCrypt.length) {
hash = hash + toCrypt.pop();
hash = hash + (hash << 10);
b = hash >> 6;
hash = (hash|b)&~(hash&b);
}
hash = hash + (hash << 3);
b = hash >> 11;
hash = (hash|b)&~(hash&b);
hash = hash + (hash << 15);
if( hash != signature ) return {"error":"bad signature"};
return {"result":"some $$$ data"};
С сервера в клиент передаётся параметр и подпись, вычисляемая как 32-битный хеш от важного параметра, id юзера (он логинится на сайт через ВК), и секрета (32-битное число). В хранимой процедуре можно проверить, что параметр не подделан.
Например, параметром может быть timestamp, до которого у юзера оплачена платная подписка. Получить текущее время на стороне ВК можно методом API.utils.getServertime()
Комментариев нет:
Отправить комментарий