added totp

This commit is contained in:
Louis Heredero 2024-12-22 02:00:37 +01:00
parent e191d82407
commit e31daa191a
Signed by: HEL
GPG Key ID: 8D83DE470F8544E7
2 changed files with 60 additions and 1 deletions

Binary file not shown.

View File

@ -1,7 +1,8 @@
#import "utils.typ": xor-bytes
#import "sha.typ": sha1
#import "md.typ": md4
#import "utils.typ": utf8-to-utf16le
#import "utils.typ": utf8-to-utf16le, z-fill
#import "base.typ": b32-decode
#let _compute-block-sized-key(key, hash-func: sha1, block-size: 64) = {
if key.len() > block-size {
@ -15,6 +16,18 @@
return key
}
#let _extract31(value) = {
let bytes = array(value)
let i = bytes.last().bit-and(0xf)
let selected-bytes = (
bytes.at(i).bit-and(0x7f),
bytes.at(i+1),
bytes.at(i+2),
bytes.at(i+3)
)
return selected-bytes.fold(0, (a, b) => a.bit-lshift(8).bit-or(b))
}
/// Hash-based Message Authentication Code
/// ```example
/// #bytes-to-hex(hmac("Key", "Hello World!"))
@ -56,4 +69,50 @@
/// -> bytes
#let ntlm(password) = {
return md4(utf8-to-utf16le(password))
}
/// Time-based One-Time Password
/// ```example
/// #let epoch = datetime(
/// year: 1970, month: 1, day: 1,
/// hour: 0, minute: 0, second: 0
/// )
/// #let date = datetime(
/// year: 2025, month: 1, day: 4,
/// hour: 12, minute: 53, second: 30
/// )
/// #totp(
/// b32-encode(bytes("YOUPI")),
/// (date - epoch).seconds()
/// )
/// ```
/// -> str
#let totp(
/// Secret key. Either bytes or a base32-encode value
/// -> str | bytes
secret,
/// Current time (seconds since t0)
/// -> int
time,
/// Time origin
/// -> int
t0: 0,
/// Code duration
/// -> int
period: 30,
/// Code length
/// -> int
digits: 6
) = {
let secret = if type(secret) == str {b32-decode(secret)} else {secret}
assert(type(secret) == bytes, message: "secret must be a string or bytes, but is " + repr(type(secret)))
let count = int(calc.div-euclid(time - t0, period))
let count-bytes = count.to-bytes(endian: "big", size: 8)
let digest = hmac(secret, count-bytes)
let hotp = _extract31(digest)
let code = calc.rem(hotp, calc.pow(10, digits))
return z-fill(str(code), digits)
}