Skip to content

Instantly share code, notes, and snippets.

@AMD-NICK
Last active December 25, 2022 17:08
Show Gist options
  • Save AMD-NICK/a27c6279496722049e24d87f134228b6 to your computer and use it in GitHub Desktop.
Save AMD-NICK/a27c6279496722049e24d87f134228b6 to your computer and use it in GitHub Desktop.
--[[-------------------------------------------------------------------------
Портирование библиотеки генерации 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