This document provides instructions for frontend developers to implement Epoch-Based Forward Secrecy in Web/A form clients.
1. Objective
The goal is to move away from a single static recipient key to a rotating set of daily keys fetched from a static JSON registry. This limits the impact of a potential private key compromise to a single 24-hour window.
2. Resource Discovery
The client should be configured with a URL to the public key registry (e.g., epoch-public.json).
<script id="weba-l2-config" type="application/json">
{
"enabled": true,
"epoch_registry_url": "/keys/epoch-public.json",
"fallback_recipient_x25519": "..."
}
</script>
3. Implementation Steps
3.1. Fetching the Registry
Use the fetchEpochRegistry function provided in the l2crypto client library.
3.2. Selecting the Active Key
Use selectEpochKey(registry) to find the key corresponding to the user's current UTC time.
import { fetchEpochRegistry, selectEpochKey } from "./l2crypto";
const config = loadL2Config();
const registry = await fetchEpochRegistry(config.epoch_registry_url);
const epochKey = registry ? selectEpochKey(registry) : null;
const recipientPk = epochKey
? b64urlDecode(epochKey.publicKey)
: b64urlDecode(config.fallback_recipient_x25519);
const recipientKid = epochKey ? epochKey.kid : config.recipient_kid;
3.3. Handling Edge Cases
- Network Failure: If the registry cannot be fetched, fall back to the
fallback_recipient_x25519(the long-term Org Root key). - Clock Skew: If the user's system clock is significantly off,
selectEpochKeymay fail to find a valid key. Fall back to the long-term key. - Inventory Depletion: If the current date is beyond the range of the registry, fall back to the long-term key.
4. UI/UX Considerations
- Background Fetch: Fetch the registry as soon as the form loads to ensure the key is ready when the user clicks "Submit".
- Encryption Indicator: The "Encrypted" badge in the UI remains the same, as the encryption algorithm (X25519/AES-GCM) is unchanged.
5. Summary of API
The following functions are available in src/form/client/l2crypto.ts:
fetchEpochRegistry(url: string): Returns the registry object.selectEpochKey(registry: EpochRegistry): Returns theEpochPublicKeyobject for the current UTC date.