oficina / calendar Public

Clone
git clone https://amadan.net/oficina/calendar

Plain git — no account needed to clone.

Download

Download this file

1package seal
2
3import (
4 "crypto/hmac"
5 "encoding/hex"
6)
7
8// Fingerprint is a KEYED, stable digest of a value: equal values give
9// equal fingerprints, and nothing else can be learned from one.
10//
11// It exists because an ordinary hash is not a seal. The app already
12// stores an unkeyed SHA-256 of an event's UID, which is fine — a UID is
13// a random string nobody can guess. An ADDRESS is the opposite: the set
14// of real email addresses is small enough to enumerate, so a plain
15// SHA-256 of "someone@example.com" is that address written in a
16// slightly inconvenient alphabet. Publishing a column of them would
17// give up exactly what the one rule promises to keep: who this team
18// meets with.
19//
20// HMAC under an HKDF-derived purpose key makes the digest useless to
21// anyone without the DEK, while still comparing equal for equal inputs
22// — which is all a dedupe or a lookup needs.
23//
24// The DEK is therefore load-bearing for lookups as well as for reading:
25// lose it and these rows can no longer be matched, exactly as sealed
26// columns can no longer be opened.
27func (s *Sealer) Fingerprint(purpose, value string) (string, error) {
28 key, err := s.purposeKey(purpose)
29 if err != nil {
30 return "", err
31 }
32 mac := hmac.New(sha256New, key)
33 mac.Write([]byte(value))
34 return hex.EncodeToString(mac.Sum(nil)), nil
35}
36