summaryrefslogtreecommitdiff
path: root/server/cmd/listend/token.go
blob: c6962a7de867606a0935cde31ae6624b5910d92f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
	"crypto/rand"
	"math/big"
	"strings"
)

// tokenAlphabet is deliberately letters and digits only, with no punctuation.
//
// This token is typed by hand into a phone. A base64url token looks stronger and is worse in
// practice: the leading "-" of one generated token was eaten by `adb shell input text` treating
// it as a flag, and "-" and "_" are both buried behind a modifier on a phone keyboard. 32
// characters of alphanumeric is ~165 bits, which is not the weak link here.
const tokenAlphabet = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"

// tokenLength is 32 characters, grouped into fours by the caller when it prints them.
const tokenLength = 32

// generateToken makes a fresh API token.
//
// From crypto/rand: this is the only thing between the open internet and a private library.
// The alphabet omits l, I, 1, O and 0 so a token read off a screen cannot be mistyped into a
// different valid-looking one.
func generateToken() (string, error) {
	limit := big.NewInt(int64(len(tokenAlphabet)))
	var out strings.Builder
	for i := 0; i < tokenLength; i++ {
		n, err := rand.Int(rand.Reader, limit)
		if err != nil {
			return "", err
		}
		out.WriteByte(tokenAlphabet[n.Int64()])
	}
	return out.String(), nil
}