| 1 | package calls |
| 2 | |
| 3 | import ( |
| 4 | "crypto/sha256" |
| 5 | "encoding/hex" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | // Review W-4: the subject was bound into the hub session key in the |
| 10 | // Task 4 fix round with a reason — "the key then cannot survive the |
| 11 | // person it belongs to" — and nothing tested it. Dropping the subject |
| 12 | // left the whole suite green. |
| 13 | // |
| 14 | // A sign-out-and-in test over HTTP does not gate this: re-signing-in |
| 15 | // hands the browser a new cookie value, so the key would change with or |
| 16 | // without the subject in the hash. What the claim is actually about is |
| 17 | // the same cookie value under a different person, which is why this is |
| 18 | // a test of the derivation rather than of a request. |
| 19 | func TestTheHubSessionKeyBindsTheSubjectTheSaltAndTheCookie(t *testing.T) { |
| 20 | const ( |
| 21 | salt = "boot-salt" |
| 22 | who = "person@example.com" |
| 23 | cookie = "a-session-cookie-value" |
| 24 | ) |
| 25 | base := hubSessionKey(salt, who, cookie) |
| 26 | |
| 27 | // Two tabs of one browser: the same key, which is what one peer per |
| 28 | // room and its takeover need (§4.2). |
| 29 | if again := hubSessionKey(salt, who, cookie); again != base { |
| 30 | t.Fatal("the same session did not derive the same key") |
| 31 | } |
| 32 | |
| 33 | for _, c := range []struct { |
| 34 | what string |
| 35 | salt, who, cookie string |
| 36 | why string |
| 37 | }{ |
| 38 | {"subject", salt, "someone.else@example.com", cookie, |
| 39 | "a cookie value reused under another person would inherit the room"}, |
| 40 | {"salt", "another-boot", who, cookie, |
| 41 | "the key would still name a participation from before a restart"}, |
| 42 | {"cookie", salt, who, "another-session-cookie", |
| 43 | "two browsers of one person would collide, and §4.4 allows four streams per person"}, |
| 44 | } { |
| 45 | if got := hubSessionKey(c.salt, c.who, c.cookie); got == base { |
| 46 | t.Fatalf("changing the %s did not change the key: %s", c.what, c.why) |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | // And the key is not a credential: it is neither the cookie value |
| 51 | // nor a bare hash of it, so a hub key on its own reaches nothing. |
| 52 | if base == cookie { |
| 53 | t.Fatal("the key is the session cookie value") |
| 54 | } |
| 55 | bare := sha256.Sum256([]byte(cookie)) |
| 56 | if base == hex.EncodeToString(bare[:]) { |
| 57 | t.Fatal("the key is an unsalted hash of the session cookie value") |
| 58 | } |
| 59 | if len(base) != 64 { |
| 60 | t.Fatalf("the key is %d characters, want 64 hex", len(base)) |
| 61 | } |
| 62 | } |
| 63 | |