Ctrl K
ComunidadGuías…

pkg/pairingcode/pairingcode.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Package pairingcode generates and validates short, human-readable codes — the
// kind a person reads off one screen and types on another (device pairing,
// invitation links). Codes use a Crockford-style alphabet with the visually
// ambiguous characters removed.
package pairingcode

import (
	"crypto/rand"
	"strings"
)

// Alphabet is a Crockford-style alphabet with the visually ambiguous characters
// removed (no 0/O, 1/I/L, or U), so a human can read a code off one screen and
// type it on another without confusion. 30 characters.
const Alphabet = "23456789ABCDEFGHJKMNPQRSTVWXYZ"

// Canonical code lengths. Device codes keep 8 (~2^39) because they live minutes
// and only a logged-in user redeems them; invitation codes use 12 (~2^59)
// because their link lives for days.
const (
	DeviceCodeLength = 8
	InviteCodeLength = 12
)

// New returns a fresh canonical code of the given length: uppercase, no
// separator. It draws from crypto/rand with rejection sampling so every
// character is uniform (a plain byte%30 would bias the first 256%30 characters).
func New(length int) string {
	rejectAtOrAbove := byte(256 - (256 % len(Alphabet)))

	out := make([]byte, 0, length)
	buf := make([]byte, length)

	for len(out) < length {
		rand.Read(buf)

		for _, b := range buf {
			if b >= rejectAtOrAbove {
				continue
			}

			out = append(out, Alphabet[int(b)%len(Alphabet)])
			if len(out) == length {
				break
			}
		}
	}

	return string(out)
}

// Normalize canonicalizes a code as typed by a user: uppercased, with the
// display grouping (hyphens) and any stray spaces removed. It does not validate
// — pair it with IsValid.
func Normalize(code string) string {
	code = strings.ToUpper(code)
	code = strings.ReplaceAll(code, "-", "")
	code = strings.ReplaceAll(code, " ", "")

	return code
}

// IsValid reports whether code is a well-formed canonical code (right length,
// only alphabet characters). Callers should Normalize first.
func IsValid(code string, length int) bool {
	if len(code) != length {
		return false
	}

	for _, r := range code {
		if !strings.ContainsRune(Alphabet, r) {
			return false
		}
	}

	return true
}