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
}
|