nx_otp.nx
buildroot/runtime/nx_otp.nx
about
otp.nx -- HOTP (RFC 4226) + TOTP (RFC 6238) one-time passwords.
Powers the 6-digit codes in Google Authenticator / Authy /
Yubico Authenticator / Microsoft Authenticator / 1Password.
HOTP = HMAC(key, counter) -> 6-digit code (event-counter based)
TOTP = HOTP(key, floor(time / period)) -- time-based variant
Standard RFC profiles use HMAC-SHA-1 for compatibility. We
ship HMAC-SHA-256 variants here because:
- SHA-1 is deprecated for new systems (rule: don't encourage)
- RFC 6238 ยง5 explicitly permits SHA-256 / SHA-512
- All major authenticator apps support SHA-256 profiles
Callers interoperating with legacy SHA-1 providers need a
separate hotp_sha1.nx we're not shipping.
Algorithm (RFC 4226):
1. HMAC = HMAC-SHA-256(key, counter as u64 big-endian)
2. offset = HMAC[31] & 0x0F (dynamic truncation)
3. truncated = read 4 bytes BE at HMAC[offset..offset+4]
4. truncated &= 0x7FFFFFFF (clear top bit)
5. code = truncated mod 10^digits
Invariants:
OTP1 digits in [6, 10]; most deployments use 6. We don't
enforce; caller picks.
OTP2 Counter is u64 big-endian; identical on every platform.
OTP3 Code is zero-padded to `digits` length on render.
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_hmac.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| none |
functions
| 40 | func hotp_value(key: *u8, key_len: i64, counter: i64, digits: i64) -> i64 |
| 72 | func otp_render(value: i64, digits: i64, out: *u8) -> i64 called by 1: hotp_sha256 |
| 84 | func hotp_sha256(key: *u8, key_len: i64, counter: i64, digits: i64, |
| 93 | func totp_sha256(key: *u8, key_len: i64, calls 1: hotp_sha256 |
| 104 | func main() -> i64 |