EncodeCursor serializes an arbitrary cursor payload (the position + filter snapshot a resource needs to resume) into the opaque, URL-safe, tamper-evident string clients echo back. The cursor is HMAC-signed (issue #144, finding M2): a client can no longer decode the base64, edit a field, and re-enco
(secret string, payload any)
| 67 | // the same key approvaltoken and the X-E2A-Auth-* email headers already use, |
| 68 | // so there is no new key to manage. |
| 69 | func EncodeCursor(secret string, payload any) (string, error) { |
| 70 | raw, err := json.Marshal(payload) |
| 71 | if err != nil { |
| 72 | return "", err |
| 73 | } |
| 74 | encoded := base64.RawURLEncoding.EncodeToString(raw) |
| 75 | sig := cursorMAC([]byte(secret), []byte(encoded)) |
| 76 | return encoded + "." + base64.RawURLEncoding.EncodeToString(sig), nil |
| 77 | } |
| 78 | |
| 79 | // DecodeCursor verifies a cursor's HMAC and reverses it into dst. A |
| 80 | // malformed, tampered, or wrong-secret cursor yields ErrInvalidCursor |