Last active
December 25, 2022 17:08
-
-
Save AMD-NICK/a27c6279496722049e24d87f134228b6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[------------------------------------------------------------------------- | |
Портирование библиотеки генерации Steam Guard TOTP (2FA) кода | |
https://github.com/MarlonColhado/SteamGenerateMobileAuthPHP | |
Сижу весь день с 2019.03.11 14:00, до утра планирую закончить | |
Проблема была в HMAC SHA1 и pack/unpack, из-за чего очень много гуглил | |
https://gist.github.com/AMD-NICK/ea1a8cf55ec2202683db2062d966ece5 | |
Находил кучу аналогов: на GO, | |
разбирал исходники плигина для хрома (js), | |
ковырял steam desktop authenficator, | |
весь день общался с вогелем насчет hmac и struct, | |
до дрожи боялся снова увидеть слово "buffer", | |
*плакал* https://img.qweqwe.ovh/1552340624371.png | |
Конечное решение (если оно будет) без сраных буферов! | |
ДА! 0:31! АВТОРИЗИРОВАЛСЯ В СТИМ ПО КОДУ С ЭТОГО СКРИПТА | |
Делаю бота @steam_code_bot | |
---------------------------------------------------------------------------]] | |
local sha1 = include("sha1.lua") | |
local function intToByte(int) | |
return bit.band(int, 0xFF) | |
end | |
local function createTimeHash(time) | |
time = math.floor(time / 30) | |
local timeArray = {} | |
for i = 8,1,-1 do | |
timeArray[i] = intToByte(time) | |
time = bit.rshift(time,8) | |
end | |
local time_hash = "" | |
for _,v in ipairs(timeArray) do | |
time_hash = time_hash .. string.char(v) | |
end | |
return time_hash | |
end | |
-- Аналог PHP unpack('C*', pack('H*', $hash)); и скорее всего implode(unpack("H*", $string)); | |
-- И PY "89abc".decode('hex') | |
-- В PHP выручило это: https://gist.github.com/8f235b9dfd1ff1dda1d63c1df77a861e | |
function string.unhex(str) -- a08572 | |
local arr = {} | |
str:gsub("%x%x", function(hh) -- a0 85 72 | |
arr[#arr + 1] = tonumber(hh,16) | |
end) | |
return arr -- {160, 133, 114} | |
end | |
-- Смещаем индексы, чтобы первым был 0 | |
-- https://img.qweqwe.ovh/1552340210203.png | |
local function lshiftArrIndexes(arr) | |
local t = {} | |
for i = 1,#arr do | |
t[i - 1] = arr[i] | |
end | |
return t | |
end | |
-- Генерит хеш и разбивает его на байты | |
local function createHMac(time_hash, decoded_secret) | |
local sHash = sha1.hmac(decoded_secret, time_hash) -- 40 символов, 20 байт | |
local tHmac = string.unhex(sHash) -- {20, bytes} | |
return tHmac | |
end | |
function generateSteamGuardCode(shared_secret, time_override_) | |
local time = time_override_ or os.time() + 10 | |
-- time = "1552341969" | |
local decoded_secret = util.Base64Decode(shared_secret) | |
local time_hash = createTimeHash(time) | |
local tHmac = createHMac(time_hash, decoded_secret) | |
tHmac = lshiftArrIndexes(tHmac) -- наверное, лучше просто ниже учитывать, что индексы с 1 | |
local byte = intToByte(bit.band(tHmac[19],0xF)) | |
local a = bit.band(tHmac[byte + 0], 0x7F) -- +0 :D | |
local b = bit.band(tHmac[byte + 1], 0xFF) | |
local c = bit.band(tHmac[byte + 2], 0xFF) | |
local d = bit.band(tHmac[byte + 3], 0xFF) | |
a = bit.lshift(a, 24) | |
b = bit.lshift(b, 16) | |
c = bit.lshift(c, 8) | |
-- prt({a,b,c,d}) | |
local codePoint = bit.bor(a,b,c,d) | |
-- print(codePoint) | |
local steamChars = "23456789BCDFGHJKMNPQRTVWXY" | |
local code = "" | |
for _ = 1,5 do | |
code = code .. steamChars[math.floor(codePoint) % #steamChars + 1] | |
codePoint = codePoint / #steamChars | |
end | |
return code | |
end | |
-- PRINT(generateSteamGuardCode("asd")) | |
-- Работает, но не используется | |
-- -- https://img.qweqwe.ovh/1552329821999.png | |
-- local STEAM_TIME_URL = "http://api.steampowered.com/ITwoFactorService/QueryTime/v0001" | |
-- local function getSteamTime(cb) | |
-- http.Post(STEAM_TIME_URL,{ | |
-- steamid = "0" | |
-- }, function(json) | |
-- local dat = util.JSONToTable(json) | |
-- cb(dat.response.server_time) | |
-- end, debug.Trace) | |
-- end | |
-- -- getSteamTime(PRINT) | |
-- function generateSteamGuardCodeEnsureTime(cb, shared_secret) | |
-- getSteamTime(function(time) | |
-- local code = generateSteamGuardCode(shared_secret, time) | |
-- cb(code) | |
-- end) | |
-- end | |
-- generateSteamGuardCodeEnsureTime(PRINT, "asd") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment