Passphrase as password
The previous voice-as-password exploration ended with a mild bummer: the perceptual audio hash matches a specific person saying a specific phrase, not the phrase itself. Sometimes you want the opposite — a group secret where anyone who knows the phrase can pass. Different feature stack, different threat model. Speech-to-text the input, normalize it, fuzzy-match against a reference string. Speaker-invariant by construction.
Explore the matcher
Set a reference phrase, pick a tolerance, then have one or two slots transcribe your voice and compare against it. Slot A vs B also shows ASR variance between takes.
The transcript users speak gets normalized and compared to this.
No transcript yet. Click Listen to record.
No transcript yet. Click Listen to record.
Configure the gate
Pick a phrase, tolerance, and optional normalization. The Enroller emits a snippet you can paste into any client page.
import PassphraseGate from "@/components/ui/PassphraseGate";
export default function Page() {
return (
<PassphraseGate
storageKey="my-passphrase-v1"
tolerance="standard"
expected="open sesame"
>
{/* Anything in here is rendered only after a matching phrase is spoken */}
<YourSecretPage />
</PassphraseGate>
);
}Try the gate
PassphraseGate is a design-system component. Anything inside renders only after a matching phrase is spoken.
Locked area
Speak: "open sesame"
Click Speak and say the phrase.
This browser doesn't support the Web Speech API. Try Chrome, Edge, or Safari.
Notes + threat model
- Pick a phrase that's easy to say but hard to guess. Multi-word combinations of common words ("blue raspberry tuesday") beat single keywords on both axes — easier for ASR to transcribe accurately, harder to brute-force.
- Default to
tolerance="standard". ASR will occasionally substitute homophones (their/there, two/to) or split tokens differently — one token edit is the realistic floor for honest attempts. - The phrase ships in your client bundle as plaintext. That's fine for a group-secret gate — the phrase is the secret you share with the group, and anyone with browser access can read it. Don't use this when the bundle reader shouldn't learn the phrase.
- Pass
debugwhile developing to see token-edit and char-ratio numbers on each rejected attempt. Tune the tolerance downward only when you've seen multiple successful attempts consistently land below the strict threshold.
Web Speech API runs ASR in the browser's engine. Chrome and Safari send audio to the vendor's cloud for transcription; this is the same as any browser-managed dictation feature, but it means audio leaves the device on those engines (Edge follows Chromium). The other two explorations (image-as-password, voice-as-password) have zero vendor dependency — only this one trades privacy for accuracy.
A drop-in upgrade exists: transformers.js + Whisper.tiny runs ONNX inference fully in-browser via WASM/WebGPU. Audio never leaves the device. Same component API, opt-in via a provider prop. The model file (~30-40MB quantized) is downloaded once on first use and can be self-hosted on your own domain to avoid third-party CDNs.
Default stays on Web Speech API. Cold-start cost (30MB model download + WASM init) is a poor fit for mobile — the primary target for these gates. Reach for Whisper when:
- desktop or self-hosted app where the bundle weight is acceptable
- privacy requirement is strict enough that audio cannot leave the device
- need to support Firefox (no Web Speech API)
- need a language not well-served by the vendor engines
Other zero-vendor options worth knowing about: vosk-browser (smaller, fixed-vocabulary), or DTW on mel features for the single-fixed-phrase case (tiny code, harder to make speaker-invariant — closer to voice-as-password than to a real phrase recognizer).
PassphraseGate is a UX gate, not a security control. The phrase is plaintext in the bundle. ASR can be defeated by replaying audio from someone else who said the phrase, or by typing the phrase into a synthesised TTS voice and playing it back to the mic. Don't put real secrets behind it.
- image-as-password: you have an image you want to use as a personal unlock token.
- voice-as-password: you want a unique-to-you voice unlock — same speaker, same phrase, same delivery.
- passphrase-as-password (here): you want a group secret — anyone who knows the phrase can pass.