Last active
June 19, 2022 21:11
-
-
Save Python1320/ec447cadb229a86d2e6bdf6db684ef3b to your computer and use it in GitHub Desktop.
HMAC-SHA256 for GMod (no binary modules)
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
-- bootstrap slow version | |
function string.tohex(str) | |
return (str:gsub('.', function (c) | |
return string.format('%02X', string.byte(c)) | |
end)) | |
end | |
-- caching fast versions | |
local t = {} | |
for i = 0, 255 do | |
t[string.char(i):tohex()] = string.char(i) | |
t[string.char(i):tohex():lower()] = string.char(i) | |
end | |
function string.fromhex(str) | |
return (str:gsub('%w%w', t)) | |
end | |
local t = {} | |
for i = 0, 255 do | |
t[string.char(i)] = string.char(i):tohex() | |
end | |
function string.tohex(str) | |
return (str:gsub('.', t)) | |
end | |
if SERVER then | |
local ok,hex = pcall(require,'hex') | |
if not ok or not hex or hex==true then hex = _G.hex end | |
if hex and hex.decode then | |
string.tohex = hex.encode | |
string.fromhex = hex.decode | |
end | |
end |
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
-- HMAC-SHA256 for GMod (no binary modules) | |
-- by Python1320 | |
local TEST = true | |
local magic_ipad = 0x36 | |
local magic_opad = 0x5c | |
local SHA256 = util.SHA256 | |
local SHA1 = util.SHA1 | |
local bit = bit | |
local SHA256_BLOCK_SIZE = 64 | |
local k_ipad_t, k_opad_t = {}, {} | |
local function hmac_sha256(text, key) | |
if #key > SHA256_BLOCK_SIZE then | |
key = SHA256(key):fromhex() | |
end | |
for i = 1, SHA256_BLOCK_SIZE do | |
local key_byte = key:byte(i) or 0x00 -- implicit padding | |
k_ipad_t[i] = string.char(bit.bxor(magic_ipad, key_byte)) | |
k_opad_t[i] = string.char(bit.bxor(magic_opad, key_byte)) | |
end | |
local k_ipad = table.concat(k_ipad_t) | |
local k_opad = table.concat(k_opad_t) | |
local inner_hash = SHA256(k_ipad .. text):fromhex() | |
local outer_hash = SHA256(k_opad .. inner_hash) | |
return outer_hash | |
end | |
local function hmac_sha1(text, key) | |
if #key > SHA256_BLOCK_SIZE then | |
key = SHA1(key):fromhex() | |
end | |
for i = 1, SHA256_BLOCK_SIZE do | |
local key_byte = key:byte(i) or 0x00 -- implicit padding | |
k_ipad_t[i] = string.char(bit.bxor(magic_ipad, key_byte)) | |
k_opad_t[i] = string.char(bit.bxor(magic_opad, key_byte)) | |
end | |
local k_ipad = table.concat(k_ipad_t) | |
local k_opad = table.concat(k_opad_t) | |
local inner_hash = SHA1(k_ipad .. text):fromhex() | |
local outer_hash = SHA1(k_opad .. inner_hash) | |
return outer_hash | |
end | |
if TEST then | |
--TODO: https://datatracker.ietf.org/doc/html/rfc2202#section-2 | |
local hmac = hmac_sha256 | |
local test_vectors = { -- https://datatracker.ietf.org/doc/html/rfc4231#section-4.4 | |
{"heck", "heeeck", "hecking heck", "f41d6ea9023fab5b9fb92b94761d9e2289c7ab3ddc8eb4e450b449bded3c5c11"}, | |
{"Test with a key shorter than the length of the HMAC output", "\x4a\x65\x66\x65", "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66" .. "\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f", "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"}, | |
{[[Test with a combined length of key and data that is larger than 64 | |
bytes (= block-size of SHA-224 and SHA-256). ]], "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" .. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" .. "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"}, | |
{[[Test with a combined length of key and data that is larger than 64 | |
bytes (= block-size of SHA-224 and SHA-256).]], "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11" .. "\x12\x13\x14\x15\x16\x17\x18\x19", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" .. "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" .. "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"}, | |
{[[Test with a key larger than 128 bytes (= block-size of SHA-384 and | |
SHA-512). ]], "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "\x54\x65\x73\x74\x20\x55\x73\x69\x6e\x67\x20\x4c\x61\x72\x67\x65\x72" .. "\x20\x54\x68\x61\x6e\x20\x42\x6c\x6f\x63\x6b\x2d\x53\x69\x7a\x65\x20" .. "\x4b\x65\x79\x20\x2d\x20\x48\x61\x73\x68\x20\x4b\x65\x79\x20\x46\x69" .. "\x72\x73\x74", "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"}, | |
{[[Test with a key and data that is larger than 128 bytes (= | |
block-size of SHA-384 and SHA-512). ]], "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" .. "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20\x75\x73" .. "\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e" .. "\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x6b\x65\x79\x20\x61" .. "\x6e\x64\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20\x74\x68\x61\x6e\x20" .. "\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20" .. "\x54\x68\x65\x20\x6b\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20" .. "\x62\x65\x20\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20" .. "\x62\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68\x65" .. "\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68\x6d\x2e", "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"} | |
} | |
for testid, test in pairs(test_vectors) do | |
local test_comment, key, text, res = unpack(test) | |
assert(hmac(text, key) == res, "test failed: " .. testid .. ': ' .. test_comment) | |
end | |
end | |
util.HMAC_SHA256 = hmac_sha256 | |
util.HMAC_SHA1 = hmac_sha1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment