-
-
Notifications
You must be signed in to change notification settings - Fork 998
Open
Description
Feature Request
Summary
The current cookie helper only supports signed cookies (HMAC-SHA256), which provides integrity but not confidentiality — the cookie value remains readable in plaintext.
This request adds encrypted cookie support using AES-256-GCM via the Web Crypto API, providing both confidentiality and integrity for cookie values.
Motivation
- Signed cookies (
setSignedCookie) prove the value wasn't tampered with, but the value is still visible (e.g.,session=user-id-123.signature). - Encrypted cookies make the value opaque — useful for storing sensitive data like session tokens, user preferences, or any data that should not be readable client-side.
- AES-256-GCM is the standard choice: authenticated encryption with a single pass.
Proposed API
Mirror the existing signed cookie API:
import {
setEncryptedCookie,
getEncryptedCookie,
generateEncryptedCookie,
} from 'hono/cookie'
// Set
await setEncryptedCookie(c, 'session', 'sensitive-data', secret)
// Get (returns string | undefined | false)
const value = await getEncryptedCookie(c, secret, 'session')
// Generate without setting on response
const cookie = await generateEncryptedCookie('session', 'sensitive-data', secret)Design
- Algorithm: AES-256-GCM via
crypto.subtle(multi-runtime: Node, Deno, Bun, CF Workers) - Key derivation: HKDF-SHA256 from
string | BufferSourcesecret (same type as signed cookies) - IV: Random 12 bytes per encryption via
crypto.getRandomValues() - AAD: Cookie name bound as additional authenticated data (prevents copying encrypted values between cookie names)
- Cookie format:
base64(iv || ciphertext || authTag), URL-encoded - Prefix support: Full
__Secure-/__Host-prefix support - Return semantics:
falseon decryption failure (tampered/wrong key), same asgetSignedCookie
Checklist
- API mirrors existing signed cookie pattern
- Uses Web Crypto API for multi-runtime compatibility
- Supports cookie prefixes (
secure,host) - All standard cookie options (domain, path, maxAge, expires, httpOnly, sameSite, etc.)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels