This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-prf-e2e-key-derivation-standard

Hardware-Anchored PRF Extension Zero-Knowledge Key Derivation Guardrail

Enforces strict cryptographic guarantees when evaluating WebAuthn Pseudo-Random Function (PRF) extensions for client-side zero-knowledge encryption. Guarantees that raw PRF outputs undergo non-extractable HKDF-SHA256 stretching, input salts remain cryptographically isolated and static per-domain, and raw symmetric key material never leaks through network payloads or persistent browser storage.

Prohibited Anti-Pattern: Exposing Unhashed PRF Output or Transmitting Derived Keys to Relying Party Servers

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Hardware-Anchored PRF Extension Zero-Knowledge Key Derivation Guardrail - Enforces strict cryptographic guarantees when evaluating WebAuthn Pseudo-Random Function (PRF) extensions for client-side zero-knowledge encryption. Guarantees that raw PRF outputs undergo non-extractable HKDF-SHA256 stretching, input salts remain cryptographically isolated and static per-domain, and raw symmetric key material never leaks through network payloads or persistent browser storage.
globs: src/**/*.{ts,tsx}, lib/**/*.{ts,tsx}, packages/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-prf-e2e-key-derivation-standard"
---

# Hardware-Anchored PRF Extension Zero-Knowledge Key Derivation Guardrail

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Exposing Unhashed PRF Output or Transmitting Derived Keys to Relying Party Servers

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn PRF (Pseudo-Random Function) Extension Key Derivation Standard. Your role is to mandate absolute zero-knowledge client-side isolation when evaluating hmac-secret/PRF credentials. Raw PRF outputs are intermediate secret components and MUST NEVER be used directly as cryptographic keys, serialized, or transmitted to Relying Party servers. All derived keys MUST be stretched via HKDF (RFC 5869) using domain-separated context, imported directly into the subtle crypto subsystem as non-extractable CryptoKey instances, and kept strictly in ephemeral memory.

## Strict Guidelines
- Engineers MUST ALWAYS check for PRF support via `PublicKeyCredential.isConditionalMediationAvailable()` and authenticator extension results before requesting PRF outputs.
- Engineers MUST ALWAYS supply a fixed, 32-byte cryptographically secure pseudorandom salt (or deterministic application context salt) to `extensions.prf.eval.first`.
- Engineers MUST ALWAYS pass the raw 32-byte PRF evaluator output through HKDF-Extract and HKDF-Expand (using `HMAC-SHA-256`) before instantiating symmetric encryption keys (e.g., AES-GCM-256).
- Engineers MUST ALWAYS import the derived key into `window.crypto.subtle` with `extractable: false` to prevent runtime exfiltration via memory inspection or third-party scripts.
- Engineers MUST NOT transmit raw PRF evaluator outputs, intermediate HKDF input keying material, or derived symmetric keys in assertion responses or API payloads to the Relying Party server.
- Engineers MUST NOT store raw PRF output or derived master keys in persistent browser storage (`localStorage`, `sessionStorage`, or unencrypted `IndexedDB`).
- Code SHOULD enforce strict domain separation by passing distinct `info` parameters into HKDF for distinct encryption sub-keys (e.g., `app-vault-encryption-v1` vs `app-signing-v1`).

## Bad vs Good Implementations
### Unsalted Direct PRF Key Extraction vs Non-Extractable HKDF Expansion

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The insecure implementation uses an insufficient salt size, sends the raw PRF evaluation bytes to the Relying Party over an HTTP API (violating the zero-knowledge guarantee), uses the raw PRF output directly as an AES key without proper HKDF key stretching, and marks the resulting key as extractable.
```typescript
async function deriveVaultKey(credentialId: string): Promise<CryptoKey> {
  // VULNERABLE: Direct extraction, extractable key, and transmitting raw PRF bytes
  const assertion = (await navigator.credentials.get({
    publicKey: {
      challenge: new Uint8Array(32),
      allowCredentials: [{ id: Buffer.from(credentialId, 'base64'), type: 'public-key' }],
      extensions: {
        prf: { eval: { first: new TextEncoder().encode('short-insecure-salt') } }
      }
    }
  })) as PublicKeyCredential;

  const extensionResults = assertion.getClientExtensionResults();
  const rawPrfOutput = extensionResults.prf?.results?.first;

  if (!rawPrfOutput) throw new Error('PRF not supported or evaluation failed');

  // CRITICAL: Transmitting PRF secret to server breaks zero-knowledge invariant
  await fetch('/api/verify-assertion', {
    method: 'POST',
    body: JSON.stringify({ credentialId, rawPrf: Array.from(new Uint8Array(rawPrfOutput)) })
  });

  // VULNERABLE: Using raw PRF output directly as AES key with extractable: true
  return window.crypto.subtle.importKey(
    'raw',
    rawPrfOutput,
    { name: 'AES-GCM' },
    true, // CRITICAL: Extractable key material in memory
    ['encrypt', 'decrypt']
  );
}
```

#### Production Standard (Correct)
> **Standard**: Ensures the 32-byte PRF output is only used as input keying material (IKM) to HKDF-SHA-256 with domain-specific context info ('e2e-vault-encryption-v1'). The resulting AES-GCM-256 key is explicitly non-extractable, and neither raw PRF material nor the derived key ever leaves client execution context.
```typescript
const DOMAIN_SALT = new Uint8Array([
  0xa4, 0x12, 0x5f, 0x89, 0xd0, 0x33, 0x41, 0x9b,
  0x7e, 0x22, 0x84, 0xc1, 0x5a, 0x9d, 0x2e, 0x77,
  0x1f, 0x6b, 0x44, 0x09, 0x38, 0xfa, 0x82, 0xbb,
  0x55, 0x6e, 0x19, 0xcd, 0x40, 0x21, 0xfe, 0x01
]);

async function deriveVaultKey(credentialId: Uint8Array): Promise<CryptoKey> {
  const assertion = (await navigator.credentials.get({
    publicKey: {
      challenge: crypto.getRandomValues(new Uint8Array(32)),
      allowCredentials: [{ id: credentialId, type: 'public-key' }],
      extensions: {
        prf: { eval: { first: DOMAIN_SALT } }
      }
    }
  })) as PublicKeyCredential | null;

  if (!assertion) throw new Error('Assertion failed');

  const extensionResults = assertion.getClientExtensionResults();
  const rawPrf = extensionResults.prf?.results?.first;
  if (!rawPrf) throw new Error('Hardware PRF evaluation failed or unsupported');

  // 1. Import raw PRF output as input keying material (IKM) for HKDF
  const ikm = await window.crypto.subtle.importKey(
    'raw',
    rawPrf,
    'HKDF',
    false,
    ['deriveKey']
  );

  // 2. Derive non-extractable AES-GCM-256 key using HKDF with domain-separated info
  const info = new TextEncoder().encode('e2e-vault-encryption-v1');
  const salt = new Uint8Array(32); // RFC 5869 allows zero salt if IKM has high entropy

  const derivedKey = await window.crypto.subtle.deriveKey(
    {
      name: 'HKDF',
      hash: 'SHA-256',
      salt,
      info
    },
    ikm,
    { name: 'AES-GCM', length: 256 },
    false, // INVARIANT: Non-extractable
    ['encrypt', 'decrypt']
  );

  return derivedKey;
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Hardware-Anchored PRF Extension Zero-Knowledge Key Derivation Guardrail

Hardware-Anchored PRF Extension Zero-Knowledge Key Derivation Guardrail defines an industrial-grade behavioral standard for security engineering. Enforces strict cryptographic guarantees when evaluating WebAuthn Pseudo-Random Function (PRF) extensions for client-side zero-knowledge encryption. Guarantees that raw PRF outputs undergo non-extractable HKDF-SHA256 stretching, input salts remain cryptographically isolated and static per-domain, and raw symmetric key material never leaks through network payloads or persistent browser storage. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Exposing Unhashed PRF Output or Transmitting Derived Keys to Relying Party Servers Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftExposing Unhashed PRF Output or Transmitting Derived Keys to Relying Party ServersCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS check for PRF support via `PublicKeyCredential.isConditionalMediationAvailable()` and authenticator extension results before requesting PRF outputs.

Engineers MUST ALWAYS check for PRF support via `PublicKeyCredential.isConditionalMediationAvailable()` and authenticator extension results before requesting PRF outputs.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST ALWAYS supply a fixed, 32-byte cryptographically secure pseudorandom salt (or deterministic application context salt) to `extensions.prf.eval.first`.

Engineers MUST ALWAYS supply a fixed, 32-byte cryptographically secure pseudorandom salt (or deterministic application context salt) to `extensions.prf.eval.first`.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST ALWAYS pass the raw 32-byte PRF evaluator output through HKDF-Extract and HKDF-Expand (using `HMAC-SHA-256`) before instantiating symmetric encryption keys (e.g., AES-GCM-256).

Engineers MUST ALWAYS pass the raw 32-byte PRF evaluator output through HKDF-Extract and HKDF-Expand (using `HMAC-SHA-256`) before instantiating symmetric encryption keys (e.g., AES-GCM-256).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST ALWAYS import the derived key into `window.crypto.subtle` with `extractable

Engineers MUST ALWAYS import the derived key into `window.crypto.subtle` with `extractable: false` to prevent runtime exfiltration via memory inspection or third-party scripts.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Engineers MUST NOT transmit raw PRF evaluator outputs, intermediate HKDF input keying material, or derived symmetric keys in assertion responses or API payloads to the Relying Party server.

Engineers MUST NOT transmit raw PRF evaluator outputs, intermediate HKDF input keying material, or derived symmetric keys in assertion responses or API payloads to the Relying Party server.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Engineers MUST NOT store raw PRF output or derived master keys in persistent browser storage (`localStorage`, `sessionStorage`, or unencrypted `IndexedDB`).

Engineers MUST NOT store raw PRF output or derived master keys in persistent browser storage (`localStorage`, `sessionStorage`, or unencrypted `IndexedDB`).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
7

Code SHOULD enforce strict domain separation by passing distinct `info` parameters into HKDF for distinct encryption sub-keys (e.g., `app-vault-encryption-v1` vs `app-signing-v1`).

Code SHOULD enforce strict domain separation by passing distinct `info` parameters into HKDF for distinct encryption sub-keys (e.g., `app-vault-encryption-v1` vs `app-signing-v1`).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Hardware-Anchored PRF Extension Zero-Knowledge Key Derivation Guardrail critical for AI coding assistants?

Enforces strict cryptographic guarantees when evaluating WebAuthn Pseudo-Random Function (PRF) extensions for client-side zero-knowledge encryption. Guarantees that raw PRF outputs undergo non-extractable HKDF-SHA256 stretching, input salts remain cryptographically isolated and static per-domain, and raw symmetric key material never leaks through network payloads or persistent browser storage. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Exposing Unhashed PRF Output or Transmitting Derived Keys to Relying Party Servers) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Hardware-Anchored