recoverycode

package
v0.10.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package recoverycode generates and matches the one-time codes that let a user back into an account when every other factor is gone.

The suite issued three strengths for the same job. ky_server_base, gridlock-server and kysignon-server produce 8 symbols over a 32-symbol alphabet — 40 bits — and store them as a bare SHA-256, which is searchable offline by anyone who reads the store, and which bypasses every other factor on the account. kypost-server produces 12 symbols and stores them under scrypt. This package issues 12.

Hashing and storage stay with the caller: the products disagree about the hash for reasons this package cannot settle, and the codes are not what diverged dangerously. What is here is the generation, the normalisation both sides of a comparison must agree on, and a lookup that does not leak which entry matched.

Index

Constants

View Source
const Alphabet = "0123456789abcdefghijklmnopqrstuv"

Alphabet has exactly 32 symbols, so a random byte modulo its length is unbiased. It is lowercase because codes are copied and pasted, and Normalize folds case anyway.

Variables

This section is empty.

Functions

func Generate

func Generate(n int) ([]string, error)

Generate returns n distinct codes formatted xxxx-xxxx-xxxx.

func MatchCode

func MatchCode(code string, digests []string, hash func(string) string) (int, bool)

MatchCode redeems what a user typed against the stored digests, and is the entry point a redemption path should use.

hash is the product's own hashing, which this package deliberately does not own — the products disagree about it for reasons it cannot settle. What this package does own is the normalisation, and that is the whole reason this function exists: the old API was a digest comparison named for codes, with two string parameters that made passing the user's raw input compile and run and simply never match. Enrolment normalised, and a redemption path that forgot to rejected a valid code during the emergency the code is for. Normalising here means both sides cannot disagree.

func MatchDigest

func MatchDigest(candidate string, digests []string) (int, bool)

MatchDigest returns the index of the stored digest equal to candidate. Both sides are already hashed; use MatchCode unless the digest was computed elsewhere.

It compares every entry rather than returning at the first hit. ky_server_base's redeem loop breaks on match, so its timing reports where in the list the code sat; the comparison itself is constant-time here as well.

An empty stored entry is a slot already redeemed and never matches, so a caller can blank a slot in place instead of removing it. Removing renumbers the list, which is how two concurrent redemptions lose one another's write.

func Normalize

func Normalize(code string) string

Normalize reduces a code to the form that is hashed and compared. A user types the separators, or does not, in whichever case their keyboard was in.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL