From 8480223506c3242a8bdcea297062b5f67672c75f Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Fri, 21 Nov 2025 19:00:47 -0800 Subject: Separate MAC by domain --- roseh.moe.go | 43 ++++++++++++++++++------------------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/roseh.moe.go b/roseh.moe.go index ffca9d5..a2e7ed2 100644 --- a/roseh.moe.go +++ b/roseh.moe.go @@ -209,7 +209,7 @@ func makeHole() string { func newWormhole(w http.ResponseWriter, r *http.Request) { hole := makeHole() - http.Redirect(w, r, "/wormhole/"+hole+"/upload?s="+base64.RawURLEncoding.EncodeToString(mac([]byte(hole))), http.StatusSeeOther) + http.Redirect(w, r, "/wormhole/"+hole+"/upload?s="+base64.RawURLEncoding.EncodeToString(mac([]byte(hole), "hole")), http.StatusSeeOther) } func wormhole(w http.ResponseWriter, r *http.Request) { @@ -309,8 +309,7 @@ func wormholeQR(w http.ResponseWriter, r *http.Request) { http.Error(w, fmt.Sprintf("Bad signature: %s", err), http.StatusBadRequest) return } - expectedMAC := mac([]byte(r.PathValue("hole"))) - if !hmac.Equal(sig, expectedMAC) { + if !verify([]byte(r.PathValue("hole")), sig, "hole") { http.Error(w, "Bad signature", http.StatusBadRequest) return } @@ -325,26 +324,17 @@ func wormholeQR(w http.ResponseWriter, r *http.Request) { const macSize = targetSecurityLevel -func mac(msg []byte) []byte { +func mac(msg []byte, purpose string) []byte { mac := hmac.New(sha256.New, secretKey) + io.WriteString(mac, purpose) + io.WriteString(mac, ":") mac.Write(msg) return mac.Sum(nil)[:macSize] } -func sign(msg []byte) []byte { - return append(msg, mac(msg)...) -} - -func verify(msg []byte) ([]byte, bool) { - if len(msg) < macSize { - return nil, false - } - msg, messageMAC := msg[:len(msg)-macSize], msg[len(msg)-macSize:] - expectedMAC := mac(msg) - if !hmac.Equal(messageMAC, expectedMAC) { - return nil, false - } - return msg, true +func verify(msg, messageMAC []byte, purpose string) bool { + expectedMAC := mac(msg, purpose) + return hmac.Equal(messageMAC, expectedMAC) } func marshalInt(x int64) []byte { @@ -390,7 +380,8 @@ func unmarshalTime(b []byte) (time.Time, bool) { } func makeToken() string { - return base64.RawURLEncoding.EncodeToString(sign(marshalTime(time.Now()))) + t := marshalTime(time.Now()) + return base64.RawURLEncoding.EncodeToString(append(t, mac(t, "auth")...)) } const cookieExpiration = 7 * 24 * time.Hour @@ -419,8 +410,11 @@ func cookieAuth(w http.ResponseWriter, r *http.Request) bool { if err != nil { return false } - msg, ok := verify(authCookie) - if !ok { + if len(authCookie) < macSize { + return false + } + msg, mac := authCookie[:len(authCookie)-macSize], authCookie[len(authCookie)-macSize:] + if !verify(msg, mac, "auth") { return false } t, ok := unmarshalTime(msg) @@ -491,7 +485,7 @@ type loginTemplateArgs struct { } func redirectLogin(w http.ResponseWriter, r *http.Request, redirect string) { - redirect += base64.RawURLEncoding.EncodeToString(mac([]byte(redirect))) + redirect += base64.RawURLEncoding.EncodeToString(mac([]byte(redirect), "redirect")) http.Redirect(w, r, *selfURL+"/login?redirect="+url.QueryEscape(redirect), http.StatusFound) } @@ -507,12 +501,11 @@ func verifyRedirect(redirect string) (string, bool) { return "", false } redirect, macBase64 := redirect[:len(redirect)-base64MacSize], redirect[len(redirect)-base64MacSize:] - messageMAC, err := base64.RawURLEncoding.DecodeString(macBase64) + mac, err := base64.RawURLEncoding.DecodeString(macBase64) if err != nil { return "", false } - expectedMAC := mac([]byte(redirect)) - if !hmac.Equal(messageMAC, expectedMAC) { + if !verify([]byte(redirect), mac, "redirect") { return "", false } return redirect, true -- cgit v1.3.1