Skip to content

feat: Add AES-256-GCM encrypted cookie support #4817

@brunorodmoreira

Description

@brunorodmoreira

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 | BufferSource secret (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: false on decryption failure (tampered/wrong key), same as getSignedCookie

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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions