carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package seeds
2
3import (
4 "crypto/sha256"
5 "crypto/subtle"
6 "encoding/base64"
7 "encoding/hex"
8 "fmt"
9 "io"
10)
11
12// ClosedGate is the import gate a rollback installs (spec §5.6 step 1): a
13// value no token's hash can equal, so the edge refuses even verify requests.
14const ClosedGate = "closed"
15
16// NewVerifyToken mints an import's verify token (spec §5.1): 32 random
17// bytes, base64url without padding. The record and the box keep only hash.
18func NewVerifyToken() (token, hash string, err error) {
19 var b [32]byte
20 if _, err := io.ReadFull(randReader, b[:]); err != nil {
21 return "", "", fmt.Errorf("seeds: mint a verify token: %w", err)
22 }
23 token = base64.RawURLEncoding.EncodeToString(b[:])
24 return token, HashToken(token), nil
25}
26
27// HashToken is the hex sha256 the record's verify_hash and the row's
28// import_gate hold.
29func HashToken(token string) string {
30 sum := sha256.Sum256([]byte(token))
31 return hex.EncodeToString(sum[:])
32}
33
34// TokenMatches reports whether token's hash is hash, in constant time. An
35// empty token, an empty hash and ClosedGate match nothing.
36func TokenMatches(hash, token string) bool {
37 if token == "" || len(hash) != sha256.Size*2 {
38 return false
39 }
40 return subtle.ConstantTimeCompare([]byte(HashToken(token)), []byte(hash)) == 1
41}
42