File
Blob: spec/tun/session.go
| 1 | package tun |
| 2 | |
| 3 | import ( |
| 4 | "crypto/sha256" |
| 5 | "encoding/binary" |
| 6 | "encoding/hex" |
| 7 | "fmt" |
| 8 | "strings" |
| 9 | |
| 10 | "go.miragespace.co/specter/spec/chord" |
| 11 | ) |
| 12 | |
| 13 | const SessionAliasPrefix = "session:" |
| 14 | |
| 15 | const EphemeralLabelPrefix = "e1-" |
| 16 | |
| 17 | func lowerHex(s string) bool { |
| 18 | for _, c := range s { |
| 19 | if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) { |
| 20 | return false |
| 21 | } |
| 22 | } |
| 23 | return true |
| 24 | } |
| 25 | |
| 26 | func IsSessionAlias(addr string) bool { |
| 27 | return len(addr) == 40 && strings.HasPrefix(addr, SessionAliasPrefix) && lowerHex(addr[len(SessionAliasPrefix):]) |
| 28 | } |
| 29 | |
| 30 | func SessionAlias(inv [16]byte) string { return SessionAliasPrefix + hex.EncodeToString(inv[:]) } |
| 31 | |
| 32 | func EphemeralLabel(home uint64, spki []byte) (label string, inv [16]byte, err error) { |
| 33 | if home >= chord.MaxIdentitifer { |
| 34 | return "", inv, fmt.Errorf("home ID exceeds 48 bits") |
| 35 | } |
| 36 | var encoded [8]byte |
| 37 | binary.BigEndian.PutUint64(encoded[:], home) |
| 38 | h := sha256.New() |
| 39 | h.Write([]byte("specter/ephemeral/v1\x00")) |
| 40 | h.Write(encoded[2:]) |
| 41 | h.Write(spki) |
| 42 | copy(inv[:], h.Sum(nil)) |
| 43 | return EphemeralLabelPrefix + hex.EncodeToString(encoded[2:]) + hex.EncodeToString(inv[:]), inv, nil |
| 44 | } |
| 45 | |
| 46 | func ParseEphemeralLabel(label string) (home uint64, inv [16]byte, ok bool) { |
| 47 | if len(label) != 47 || !strings.HasPrefix(label, EphemeralLabelPrefix) || !lowerHex(label[3:]) { |
| 48 | return |
| 49 | } |
| 50 | raw, _ := hex.DecodeString(label[3:]) |
| 51 | for _, b := range raw[:6] { |
| 52 | home = home<<8 | uint64(b) |
| 53 | } |
| 54 | copy(inv[:], raw[6:]) |
| 55 | return home, inv, true |
| 56 | } |