UnENVerse 0.42.6
Local-first desktop secrets manager — TypeScript frontend
Loading...
Searching...
No Matches
totp.ts File Reference

Stored TOTP seeds — the authenticator half of the vault (Phase 22). More...

import st;
Include dependency graph for totp.ts:

Variables

export type TotpAlgorithm = 'SHA1' | 'SHA256' | 'SHA512'
 HMAC an otpauth:// URI may name.
 
export type TotpKind = 'totp' | 'hotp' | 'steam'
 What a stored seed is, which decides what "the current code" means for it.
 
export const STEAM_ALPHABET = '23456789BCDFGHJKMNPQRTVWXY'
 Characters a Steam code is drawn from.
 
export const STEAM_DIGITS = 5
 How many characters a Steam code carries.
 
export const TOTP_DEFAULTS
 What a URI means when it omits the parameter — and so what a bare seed means.
 
export const MIN_DIGITS = 6
 Fewest digits a code may carry (RFC 4226's floor).
 
export const MAX_DIGITS = 10
 Most digits a code may carry.
 
export const MAX_PERIOD_SECS = 3600
 Longest step a stored seed may name.
 
export interface TotpParams
 What a seed is, and the numbers it is generated under.
 
algorithm __pad0__
 
digits __pad1__
 
period __pad2__
 
counter __pad3__
 The next counter an hotp seed will use.
 
issuer __pad4__
 The service, when the URI named one.
 
account __pad5__
 The account at that service, when the URI named one.
 
const B32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
 

Detailed Description

Stored TOTP seeds — the authenticator half of the vault (Phase 22).

@description A totp_secret on an entry is a seed a third-party service issued, from which UnENVerse produces the six digits you type into that service. It is the mirror image of the Phase 19 TOTP, which is a second factor on UnENVerse's own sub-user login and lives in the users table; the two share the RFC 6238 arithmetic in vault-core/src/totp.rs and nothing else.

What is here and what is deliberately not

Parsing lives here and in vault-core/src/totp.rs, as a twin pair pinned by tests/fixtures/parity/totp-seeds.json — the same arrangement as ratelimit.ts/ratelimit.rs. It has to exist here because the add/edit form splits a pasted otpauth:// URI as you type, before anything is saved.

Code generation does not. There is exactly one HMAC implementation in this project and it is the Rust one: a second would be a second thing to get wrong, and getting it wrong produces six digits that look right and are rejected by a service with no explanation. The app asks Rust over IPC (entry_totp_code), which is the shape pools.ts already uses and the one CLAUDE.md's twin-pair table says to prefer.

The cost of that choice is that a browser-only dev server (npm run dev, no Tauri) cannot show a code. It says so rather than showing a wrong one.

Variable Documentation

◆ TotpAlgorithm

export type TotpAlgorithm = 'SHA1' | 'SHA256' | 'SHA512'

HMAC an otpauth:// URI may name.

◆ TotpKind

export type TotpKind = 'totp' | 'hotp' | 'steam'

What a stored seed is, which decides what "the current code" means for it.

The three differ in where the counter comes from, not in the arithmetic: totp divides the clock by the period, steam does the same and renders the result in Steam's five-character alphabet, and hotp has no clock at all and uses a number the vault stores and the user advances.

Phase 22 refused the last two. That was right while nothing could store a counter — an hotp entry with nowhere to keep its position shows a code that never changes — and Phase 22.2 gives it somewhere.

◆ STEAM_ALPHABET

export const STEAM_ALPHABET = '23456789BCDFGHJKMNPQRTVWXY'

Characters a Steam code is drawn from.

Here only to validate what Rust made.

◆ STEAM_DIGITS

export const STEAM_DIGITS = 5

How many characters a Steam code carries.

Steam fixes it; it is not a setting.

◆ TOTP_DEFAULTS

export const TOTP_DEFAULTS
Initial value:
= {
kind: 'totp' as TotpKind,
algorithm: 'SHA1' as TotpAlgorithm,
digits: 6,
period: 30,
counter: 0,
} as const
let kind
Definition bundle-import.ts:196
export type TotpKind
What a stored seed is, which decides what "the current code" means for it.
Definition totp.ts:50
export type TotpAlgorithm
HMAC an otpauth:// URI may name.
Definition totp.ts:36

What a URI means when it omits the parameter — and so what a bare seed means.

◆ MIN_DIGITS

export const MIN_DIGITS = 6

Fewest digits a code may carry (RFC 4226's floor).

◆ MAX_DIGITS

export const MAX_DIGITS = 10

Most digits a code may carry.

Ten is where the 31-bit truncated value runs out; an eleventh digit would be a constant zero that looks like part of the code.

◆ MAX_PERIOD_SECS

export const MAX_PERIOD_SECS = 3600

Longest step a stored seed may name.

An hour; nothing real uses more.

◆ TotpParams

export interface TotpStored extends TotpParams
Initial value:

What a seed is, and the numbers it is generated under.

A parsed seed: the secret plus everything the URI said about it.

◆ __pad0__

algorithm __pad0__

◆ __pad1__

digits __pad1__

◆ __pad2__

period __pad2__

◆ __pad3__

counter __pad3__

The next counter an hotp seed will use.

Zero for the other two kinds.

State, not configuration — the only number here a correct implementation writes back, which is why advancing it is an explicit action rather than a side effect of reading a code.

◆ __pad4__

issuer __pad4__

The service, when the URI named one.

Offered to the form, never forced.

◆ __pad5__

account __pad5__

The account at that service, when the URI named one.

◆ B32

const B32 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'