# OTP (TOTP)

```c
#define FIO_OTP
#include "fio-stl.h"
```

Time-based One-Time Password helper. Implements the TOTP algorithm over HMAC-SHA-1, compatible with common authenticator apps. It can generate keys, encode them as Base32, and compute codes for the current time or a fixed timestamp.

### Types

#### `fio_otp_settings_s`

```c
typedef struct {
  /** The time interval for TOTP rotation. */
  size_t interval; /* 30 == Google OTP */
  /** The number of digits in the OTP. */
  size_t digits; /* 6 == Google OTP */
  /** The time offset (in `interval` units) from the current time. */
  int64_t offset; /* 0 == Google OTP */
  /** Set to true if the secret / key is in Hex instead of Base32. */
  uint8_t is_hex;
  /** Set to true if the secret / key is raw bit data (no encoding). */
  uint8_t is_raw;
} fio_otp_settings_s;
```

Configuration for OTP generation. Fields omitted in the named-argument macro call default to zero; the implementation then substitutes the Google-OTP defaults (30-second interval, 6 digits, zero offset).

### API Functions

#### `fio_otp_generate_key`

```c
FIO_IFUNC fio_u128 fio_otp_generate_key(void);
```

Generates a cryptographically secure random 128-bit key.

**Returns:** a 16-byte random key suitable for TOTP secrets.

#### `fio_otp_print_key`

```c
FIO_IFUNC size_t fio_otp_print_key(char *dest, uint8_t *key, size_t len);
```

Encodes a key as a Base32 string for sharing with authenticator apps.

**Parameters:**
- `dest` — output buffer. Must be at least `len * 2 + 1` bytes.
- `key` — key bytes; if `NULL`, a new random key is generated and encoded.
- `len` — key length in bytes.

**Returns:** length of the encoded string written to `dest`.

#### `fio_otp`

```c
SFUNC uint32_t fio_otp(fio_buf_info_s secret, fio_otp_settings_s settings);
/* Named arguments using macro. */
#define fio_otp(secret, ...) fio_otp(secret, (fio_otp_settings_s){__VA_ARGS__})
```

Computes a TOTP for the current wall-clock time.

**Parameters:**
- `secret` — shared secret as a `fio_buf_info_s`.

**Named Arguments:**
| Argument | Type | Description |
|---|---|---|
| `interval` | `size_t` | rotation interval in seconds; defaults to 30 |
| `digits` | `size_t` | number of output digits; defaults to 6 |
| `offset` | `int64_t` | interval offset from now; defaults to 0 |
| `is_hex` | `uint8_t` | set if `secret` is Hex encoded |
| `is_raw` | `uint8_t` | set if `secret` is raw bytes |

**Returns:** the OTP value.

#### `fio_otp_at`

```c
SFUNC uint32_t fio_otp_at(fio_buf_info_s secret,
                          uint64_t unix_time,
                          fio_otp_settings_s settings);
/* Named arguments using macro. */
#define fio_otp_at(secret, unix_time, ...)                                     \
  fio_otp_at(secret, unix_time, (fio_otp_settings_s){__VA_ARGS__})
```

Computes a TOTP for a specific Unix timestamp. Useful for tests and RFC vectors.

**Parameters:**
- `secret` — shared secret as a `fio_buf_info_s`.
- `unix_time` — timestamp to compute the OTP for.

**Named Arguments:** same as `fio_otp`.

**Returns:** the OTP value.

### Example

```c
#define FIO_OTP
#include "fio-stl.h"

int main(void) {
  /* Generate and print a new Base32 secret. */
  char key_str[64];
  fio_otp_print_key(key_str, NULL, 0);
  printf("secret: %s\n", key_str);

  /* Compute the current 6-digit code. */
  uint32_t code = fio_otp(FIO_BUF_INFO1(key_str));
  printf("code: %06u\n", code);
  return 0;
}
```

------------------------------------------------------------
