mirror of
https://git.phreedom.club/localhost_frssoft/fediauth.git
synced 2024-11-26 01:41:32 +00:00
working otp code generation
This commit is contained in:
parent
64eb6077b3
commit
831ba7772e
20
.github/workflows/test.yml
vendored
Normal file
20
.github/workflows/test.yml
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
name: test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
strategy:
|
||||
matrix:
|
||||
ENGINE_VERSION: [5.3.0, 5.4.0, 5.5.0, 5.6.1, latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
- name: test
|
||||
run: docker-compose up --exit-code-from test
|
15
docker-compose.yml
Normal file
15
docker-compose.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
version: "3.6"
|
||||
|
||||
services:
|
||||
test:
|
||||
build: ./test
|
||||
user: root
|
||||
volumes:
|
||||
- "./:/root/.minetest/worlds/world/worldmods/otp/"
|
||||
- "./test/minetest.conf:/minetest.conf"
|
||||
- "world:/root/.minetest/worlds/world"
|
||||
ports:
|
||||
- "30000:30000/udp"
|
||||
|
||||
volumes:
|
||||
world: {}
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
-- https://stackoverflow.com/a/25594410
|
||||
function otp.bitXOR(a,b)--Bitwise xor
|
||||
local function bitxor(a,b)
|
||||
local p,c=1,0
|
||||
while a>0 and b>0 do
|
||||
local ra,rb=a%2,b%2
|
||||
|
@ -16,6 +16,16 @@ function otp.bitXOR(a,b)--Bitwise xor
|
|||
return c
|
||||
end
|
||||
|
||||
local function bitor(a,b)
|
||||
local p,c=1,0
|
||||
while a+b>0 do
|
||||
local ra,rb=a%2,b%2
|
||||
if ra+rb>0 then c=c+p end
|
||||
a,b,p=(a-ra)/2,(b-rb)/2,p*2
|
||||
end
|
||||
return c
|
||||
end
|
||||
|
||||
-- https://stackoverflow.com/a/32387452
|
||||
local function bitand(a, b)
|
||||
local result = 0
|
||||
|
@ -36,15 +46,20 @@ local function rshift(x, by)
|
|||
return math.floor(x / 2 ^ by)
|
||||
end
|
||||
|
||||
function otp.write_uint64(v)
|
||||
local b1 = bitand(v, 0xFF)
|
||||
local b2 = bitand( rshift(v, 8), 0xFF )
|
||||
local b3 = bitand( rshift(v, 16), 0xFF )
|
||||
local b4 = bitand( rshift(v, 24), 0xFF )
|
||||
local b5 = bitand( rshift(v, 32), 0xFF )
|
||||
local b6 = bitand( rshift(v, 40), 0xFF )
|
||||
local b7 = bitand( rshift(v, 48), 0xFF )
|
||||
local b8 = bitand( rshift(v, 56), 0xFF )
|
||||
local function lshift(x, by)
|
||||
return x * 2 ^ by
|
||||
end
|
||||
|
||||
-- big-endian uint64 of a number
|
||||
function otp.write_uint64_be(v)
|
||||
local b1 = bitand( rshift(v, 56), 0xFF )
|
||||
local b2 = bitand( rshift(v, 48), 0xFF )
|
||||
local b3 = bitand( rshift(v, 40), 0xFF )
|
||||
local b4 = bitand( rshift(v, 32), 0xFF )
|
||||
local b5 = bitand( rshift(v, 24), 0xFF )
|
||||
local b6 = bitand( rshift(v, 16), 0xFF )
|
||||
local b7 = bitand( rshift(v, 8), 0xFF )
|
||||
local b8 = bitand( rshift(v, 0), 0xFF )
|
||||
return string.char(b1, b2, b3, b4, b5, b6, b7, b8)
|
||||
end
|
||||
|
||||
|
@ -61,29 +76,49 @@ end
|
|||
function otp.hmac(key, message)
|
||||
local i_key_pad = ""
|
||||
for i=1,64 do
|
||||
i_key_pad = i_key_pad .. string.char(otp.bitXOR(string.byte(key, i) or 0x00, string.byte(i_pad, i)))
|
||||
i_key_pad = i_key_pad .. string.char(bitxor(string.byte(key, i) or 0x00, string.byte(i_pad, i)))
|
||||
end
|
||||
assert(#i_key_pad == 64)
|
||||
|
||||
local o_key_pad = ""
|
||||
for i=1,64 do
|
||||
o_key_pad = o_key_pad .. string.char(otp.bitXOR(string.byte(key, i) or 0x00, string.byte(o_pad, i)))
|
||||
o_key_pad = o_key_pad .. string.char(bitxor(string.byte(key, i) or 0x00, string.byte(o_pad, i)))
|
||||
end
|
||||
assert(#o_key_pad == 64)
|
||||
|
||||
-- concat message
|
||||
local first_msg = i_key_pad
|
||||
for i=1,#message do
|
||||
first_msg = first_msg .. string.byte(message, i)
|
||||
first_msg = first_msg .. string.char(string.byte(message, i))
|
||||
end
|
||||
assert(#first_msg == 64+8)
|
||||
|
||||
-- hash first message
|
||||
local hash_sum_1 = minetest.sha1(first_msg, true)
|
||||
assert(#hash_sum_1 == 20)
|
||||
|
||||
-- concat first message to secons
|
||||
local second_msg = o_key_pad
|
||||
for i=1,#hash_sum_1 do
|
||||
second_msg = second_msg .. string.byte(hash_sum_1, i)
|
||||
second_msg = second_msg .. string.char(string.byte(hash_sum_1, i))
|
||||
end
|
||||
assert(#second_msg == 64+20)
|
||||
|
||||
-- hash final message
|
||||
return minetest.sha1(second_msg, true)
|
||||
local hmac = minetest.sha1(second_msg, true)
|
||||
assert(#hmac == 20)
|
||||
|
||||
return hmac
|
||||
end
|
||||
|
||||
function otp.generate_code(key, message)
|
||||
local hmac = otp.hmac(key, message)
|
||||
|
||||
-- https://www.rfc-editor.org/rfc/rfc4226#section-5.4
|
||||
local offset = bitand(string.byte(hmac, #hmac), 0xF)
|
||||
local value = 0
|
||||
value = bitor(value, string.byte(hmac, offset+4))
|
||||
value = bitor(value, lshift(string.byte(hmac, offset+3), 8))
|
||||
value = bitor(value, lshift(string.byte(hmac, offset+2), 16))
|
||||
value = bitor(value, lshift(bitand(string.byte(hmac, offset+1), 0x7F), 24))
|
||||
return value % 10^6
|
||||
end
|
43
functions.spec.lua
Normal file
43
functions.spec.lua
Normal file
|
@ -0,0 +1,43 @@
|
|||
|
||||
|
||||
mtt.register("otp.hmac", function(callback)
|
||||
local secret_b32 = "N6JGKMEKU2E6HQMLLNMJKBRRGVQ2ZKV7"
|
||||
local secret = otp.basexx.from_base32(secret_b32)
|
||||
local unix_time = 1640995200
|
||||
|
||||
local expected_hmac = otp.basexx.from_base64("m04YheEb7i+ThPMUJEfVXVybZFo=")
|
||||
assert(#expected_hmac == 20)
|
||||
|
||||
local tx = 30
|
||||
local ct = math.floor(unix_time / tx)
|
||||
local counter = otp.write_uint64_be(ct)
|
||||
|
||||
assert( #secret == 20 )
|
||||
assert( otp.basexx.to_base64(secret) == "b5JlMIqmiePBi1tYlQYxNWGsqr8=" )
|
||||
assert( #counter == 8 )
|
||||
assert( otp.basexx.to_base64(counter) == "AAAAAANCp0A=" )
|
||||
|
||||
local hmac = otp.hmac(secret, counter)
|
||||
assert(#hmac == 20)
|
||||
|
||||
for i=1,20 do
|
||||
assert( string.byte(expected_hmac,i) == string.byte(hmac, i) )
|
||||
end
|
||||
|
||||
callback()
|
||||
end)
|
||||
|
||||
mtt.register("otp.generate_code", function(callback)
|
||||
local expected_code = 699847
|
||||
local secret_b32 = "N6JGKMEKU2E6HQMLLNMJKBRRGVQ2ZKV7"
|
||||
local secret = otp.basexx.from_base32(secret_b32)
|
||||
local unix_time = 1640995200
|
||||
|
||||
local tx = 30
|
||||
local ct = math.floor(unix_time / tx)
|
||||
local counter = otp.write_uint64_be(ct)
|
||||
|
||||
local code = otp.generate_code(secret, counter)
|
||||
assert(code == expected_code)
|
||||
callback()
|
||||
end)
|
5
init.lua
5
init.lua
|
@ -9,4 +9,7 @@ otp = {
|
|||
}
|
||||
|
||||
dofile(MP.."/functions.lua")
|
||||
dofile(MP.."/test.lua")
|
||||
|
||||
if minetest.get_modpath("mtt") and mtt.enabled then
|
||||
dofile(MP.."/functions.spec.lua")
|
||||
end
|
24
test.lua
24
test.lua
|
@ -1,24 +0,0 @@
|
|||
local secret_b32 = "N6JGKMEKU2E6HQMLLNMJKBRRGVQ2ZKV7"
|
||||
local expected_code = 699847
|
||||
|
||||
minetest.register_chatcommand("otp_test", {
|
||||
description = "",
|
||||
params = "[]",
|
||||
func = function(name, param)
|
||||
local secret = otp.basexx.from_base32(secret_b32)
|
||||
local unix_time = 1640995200
|
||||
local tx = 30
|
||||
local ct = math.floor(unix_time / tx)
|
||||
|
||||
local hmac = otp.hmac(secret, otp.write_uint64(ct))
|
||||
|
||||
|
||||
|
||||
print(dump({
|
||||
expected_code = expected_code,
|
||||
unix_time = unix_time,
|
||||
ct = ct,
|
||||
hmac = otp.basexx.to_base64(hmac)
|
||||
}))
|
||||
end
|
||||
})
|
11
test/Dockerfile
Normal file
11
test/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
|||
ARG ENGINE_VERSION=5.6.1
|
||||
FROM registry.gitlab.com/minetest/minetest/server:${ENGINE_VERSION}
|
||||
|
||||
USER root
|
||||
|
||||
RUN apk add git &&\
|
||||
mkdir -p /root/.minetest/worlds/world/worldmods/ &&\
|
||||
cd /root/.minetest/worlds/world/worldmods/ &&\
|
||||
git clone https://github.com/BuckarooBanzay/mtt
|
||||
|
||||
ENTRYPOINT minetestserver --config /minetest.conf
|
3
test/minetest.conf
Normal file
3
test/minetest.conf
Normal file
|
@ -0,0 +1,3 @@
|
|||
default_game = minetest_game
|
||||
mg_name = v7
|
||||
mtt_enable = true
|
Loading…
Reference in a new issue