Documentation
¶
Overview ¶
Package shortcode is a kit for apps that hand out short codes (a link shortener, an invitation code): the alphabets a code is drawn from, the one canonical form a code is stored and looked up by, crypto/rand generation, and the guessing arithmetic a setup screen shows. It runs in the app's module; filex itself keeps none of an app's codes.
The arithmetic assumes filex's own miss limiter on an app's public route (MissesPerDay): the host counts the visits an app answered "miss" and holds a client back past that many.
Index ¶
- Constants
- Variables
- func Bits(size, n int) float64
- func Canonical(code string, caseSensitive bool) (string, bool)
- func CheckAlias(alias string, caseSensitive bool) (string, error)
- func DecodeSegment(escaped string) (string, bool)
- func EscapePath(code string) string
- func FoldRune(r rune) rune
- func GuessDays(bits float64, links, addresses int) float64
- func Key(canonical string) string
- func ReservedCode(canonical string) bool
- func SymbolAllowed(r rune) bool
- func Symbols(code string) int
- type Alphabet
- func (a Alphabet) Bits(n int) float64
- func (a Alphabet) CaseSensitive() bool
- func (a Alphabet) CheckRule(n int) error
- func (a Alphabet) Generate(n int) (string, error)
- func (a Alphabet) MinLengthFor(bits float64) int
- func (a Alphabet) Preset() string
- func (a Alphabet) Size() int
- func (a Alphabet) Symbols() string
Constants ¶
const ( PresetDigits = "digits" // 0-9 PresetAlnum = "alnum" // A-Z a-z 0-9 (a-z 0-9 when case does not matter) PresetURLSafe = "url-safe" // alnum and - . _ ~ (RFC 3986 "unreserved") PresetEmoji = "emoji" // emoji.txt PresetCustom = "custom" )
The alphabets the setup wizard offers. A custom set is the administrator's own list of symbols.
const ( // MinBits is the floor of a generated code's keyspace, in bits // (log2 of |alphabet|^length). A rule under it cannot be saved. // // Why 45: filex's miss limiter lets one client make MissesPerDay wrong // guesses a day. An attacker with 10,000 addresses against 100,000 live // links finds ONE of them, on average, after // 2^45 / (100,000 × 10,000 × 100) ≈ 350 days - and the instance raises // an alarm long before. 40 bits is about 11 days under the same attacker. MinBits = 45 // GoodBits is where the wizard stops warning. GoodBits = 50 // MaxLength is the longest generated code (and alias), in symbols. MaxLength = 64 // MinCustomSymbols / MaxCustomSymbols bound a custom set. MinCustomSymbols = 2 MaxCustomSymbols = 4096 // MinAliasLength is the shortest alias an app may ask for. MinAliasLength = 3 )
The limits on a code rule.
const ( ModelAttackerAddresses = 10000 ModelLiveLinks = 100000 )
The attacker the wizard's estimate assumes (GuessDays).
const MissesPerDay = 100
MissesPerDay is the most wrong guesses filex lets one client make in a day on an app's public route before its miss limiter holds the client back (internal/shortlink; a test there keeps the two equal).
Variables ¶
var ( ErrPreset = errors.New("short_link_alphabet_unknown") ErrCustomSymbols = errors.New("short_link_alphabet_symbols") ErrSymbol = errors.New("short_link_alphabet_symbol") ErrCollision = errors.New("short_link_alphabet_collision") ErrLength = errors.New("short_link_length") ErrTooWeak = errors.New("short_link_too_weak") ErrCode = errors.New("short_link_code_invalid") )
Errors a rule or a code is refused with. The API answers them as codes.
Functions ¶
func Canonical ¶
Canonical is the canonical form of a code: NFC, variation selectors removed, and - when case does not matter - every symbol folded (FoldRune). ok is false for what can never be a code: empty, longer than MaxLength symbols, or holding a symbol SymbolAllowed refuses (a space, a control or invisible character, a URL delimiter, an emoji sequence joiner or a skin-tone modifier).
func CheckAlias ¶
CheckAlias validates a code an app chose (an alias) and answers its canonical form: at least MinAliasLength symbols, each one SymbolAllowed, and not a reserved path. An alias need not be drawn from the alphabet, and it is outside the keyspace floor - a word is guessable by nature.
func DecodeSegment ¶
DecodeSegment reads one ESCAPED path segment (from URL.EscapedPath) into text: percent escapes decoded once, the result valid UTF-8 with no `/` (an escaped slash is not part of a code). ok is false for anything else.
func EscapePath ¶
EscapePath is the code as it goes into a link that is copied, mailed or handed to a chat: every byte outside ASCII percent-encoded (UTF-8), so a messenger that would stop a link at the first emoji sees one unbroken address. A browser shows it decoded in its address bar.
func FoldRune ¶
FoldRune is the case-insensitive form of one symbol: the lower case of its upper case. So `A`, `a` fold to `a`, and `i`, `ı`, `I`, `İ` all fold to `i` - which is why a case-insensitive custom set may hold only one of them.
func GuessDays ¶
GuessDays is how many days, on average, an attacker with `addresses` addresses, each held to MissesPerDay wrong guesses a day, needs to find ONE of `links` live links in a keyspace of `bits` bits. +Inf when nothing is guessing.
func ReservedCode ¶
ReservedCode reports a canonical code that is one of those paths.
func SymbolAllowed ¶
SymbolAllowed reports whether r may be a symbol of a code: a letter, a number, one of `- . _ ~`, or an emoji of the emoji set. Nothing that ends a path segment or means something in a URL (`/ ? # % + &` ...), no space, no control or invisible character, no combining mark on its own.
Types ¶
type Alphabet ¶
type Alphabet struct {
// contains filtered or unexported fields
}
Alphabet is the set of symbols generated codes are drawn from, and whether a visitor's code is matched with case.
func NewAlphabet ¶
NewAlphabet builds one of the presets, or a custom set from custom (every rune one symbol; spaces and commas between them are ignored).
When case does not matter, the letters are matched folded (FoldRune): a preset draws lower-case letters only, and a custom set may not hold two symbols that fold to the same one (`a` and `A`; `i`, `ı`, `I` and `İ`), since a visitor could not tell the codes apart.
func (Alphabet) CaseSensitive ¶
CaseSensitive reports whether codes are matched with case.
func (Alphabet) Generate ¶
Generate draws a code of n symbols, every symbol uniformly and independently from crypto/rand (rejection sampling: no modulo bias, no sequence, nothing derived from a clock or a counter).
func (Alphabet) MinLengthFor ¶
MinLengthFor is the shortest code of this alphabet that reaches MinBits.