Skip to main content

ZZPass Security Whitepaper

Last updated 2026-10-20.

ZZPass is an end-to-end-encrypted password manager for iOS and macOS. This document describes its trust model, cryptographic design, and the security properties of its sync, sharing, and time-locked-access features. It is written so that a security researcher can verify the claims against the source — the server components are open source (see Open source & verifiability) and vault encryption uses only standard primitives from Apple's CryptoKit and CommonCrypto.

We state limitations as plainly as guarantees. A password manager earns trust by being precise about what it cannot do, not only what it can.

1. Trust model

The design goal is zero-knowledge: ZZPass (the operator) and the sync transport (Apple iCloud/CloudKit) can never read your vault. All encryption and decryption happen on your device, under keys derived from your primary password, which never leaves the device.

What each party can see:

PartyCan seeCannot see
ZZPass operatorNothing about vault contents. Our own servers hold ciphertext, timing/audit metadata, anonymous aggregates — and, for emergency access only, an owner-provided notification email while the deposit can still be denied (§6).Passwords, notes, attachments, titles, URLs, keys, your primary password.
Apple / CloudKitEncrypted record blobs, record counts, sync metadata, your Apple ID (for their own sync).Plaintext of any field — everything sensitive is encrypted before it reaches CloudKit.
A network attackerTLS-protected traffic only.Plaintext (TLS + the payloads are already E2E-encrypted underneath).

Consequences of zero-knowledge, stated honestly:

2. Cryptographic primitives

ZZPass implements no custom cryptography. It composes standard primitives from Apple CryptoKit and CommonCrypto:

PurposePrimitive
Password-based key derivationPBKDF2-HMAC-SHA256, 650,000 iterations
Sub-key derivationHKDF-SHA256
Symmetric encryption (data at rest, sealed payloads)AES-256-GCM (authenticated)
Public-key key agreement / key wrapping (ECIES)P-256 ECDH
Digital signatures (group manifests, escrow deposits, update signing)P-256 ECDSA (SHA-256) and Ed25519 (app-update signing)
Message authentication (escrow tokens)HMAC-SHA256 (constant-time verification)
Hashing / identifiersSHA-256

650,000 PBKDF2-SHA256 iterations exceeds current OWASP guidance (600,000). AES-256-GCM is authenticated, so tampering with a ciphertext is detected on decrypt.

3. Account keys and the key hierarchy

primary password ─PBKDF2-SHA256(650k, per-account salt)──▶ master key (AES-256)
                                                    │
                          ┌─────────────────────────┼──────────────────────────┐
                   HKDF-SHA256                 protects                    HKDF-SHA256
                          │                        │                           │
                   E2E identity key       vault data (AES-256-GCM)     other sub-keys
                   (P-256 keypair)        via value transformers

4. Data at rest and sync

Persistence is a dual Core Data + CloudKit store: a private store for your own vault and a separate shared store (.shared CloudKit scope) for shared groups. Every sensitive field is encrypted on-device before it is written to Core Data, so what CloudKit replicates is ciphertext. CloudKit sees encrypted blobs and sync metadata; it never sees plaintext or keys.

A credential or note belongs to either your private vault or a shared group, never both. Sharing does not move your original (see §5).

5. Secure sharing (E2E-encrypted shared vaults)

Shared groups let members see the same items without any party outside the group — ZZPass or CloudKit — being able to read them.

Per-group keys and key distribution

Each shared group has its own AES-256 group key. Shared items carry an E2E-encrypted JSON payload sealed under that group key. The group key is distributed to members by wrapping it to each member's P-256 public key using ECDH (ECIES) — only the holder of the matching private key can unwrap it. The operator and CloudKit only ever see the wrapped (ciphertext) form.

Copy-on-share

Sharing an item creates a linked copy: the private original stays in your vault, and a shared copy goes to the group, linked bidirectionally. Your plaintext original is never exposed to the group key; the shared copy is re-sealed under the group key.

Owner-signed group state and out-of-band verification

Group membership and the key ring are not taken on trust from whoever last wrote to CloudKit. ZZPass uses an owner-signed group manifest (P-256 ECDSA) that commits to the group's key-ring hashes and member roster; clients fail closed and refuse to adopt a ring that doesn't match the owner's signed commitment. This defeats a malicious co-member, a compromised server, or a network attacker trying to substitute keys or roster.

6. Time capsules and emergency access (zero-knowledge escrow)

Two features let a key reach someone later, under a condition: Time Capsules (release at a set date) and Emergency Access (a dead-man's switch — recipients gain access if the owner goes silent). Both are backed by one primitive: a server-enforced deadline on zero-knowledge-sealed keys, implemented by an open-source Cloudflare Worker (timelock-escrow).

Security properties of the escrow server:

The escrow server holds the one piece of state whose loss is unrecoverable in the dead-owner case; its disaster-recovery posture is documented in the timelock-escrow repository.

7. Autofill and browser integration

Credential AutoFill on iOS and macOS retrieves credentials through the on-device encryption boundary: plaintext is produced only in-process, only while the vault is unlocked, and is never transmitted.

A browser extension is in development and not released yet. Its source is already public (zzpass-browser-extension). It is designed to talk to a native messaging host on the same machine, so no vault data would cross the network in the clear.

8. Telemetry and privacy

Telemetry is anonymous, coarse, and opt-out, and its ingest server is open source (zzpass-telemetry) so the claims are verifiable:

9. Threat model summary

Defended:

Explicitly out of scope (assumptions):

10. Open source & verifiability

The server components are published as standalone MIT-licensed repositories so anyone can audit exactly what runs:

The app itself is not open source. Vault encryption uses Apple CryptoKit and CommonCrypto, with no bespoke algorithms. Encrypted device-to-device connections use zzpass-core, a Rust library built on the open-source RustCrypto crates.

11. Reporting a security issue

We welcome reports from security researchers and treat them as a priority. If you believe you have found a vulnerability, please tell us before disclosing it publicly.

Contact. Email security@zzpass.com. Our machine-readable contact information is published at https://www.zzpass.com/.well-known/security.txt (RFC 9116). If your report is sensitive enough to need an encrypted channel, say so in a first plain message and we will arrange one. Please do not open a public GitHub issue for a security vulnerability.

What to include. The affected component and version, a description of the issue, steps to reproduce (a proof-of-concept if you have one), and the impact you believe it has. For a password manager we are especially interested in anything touching cryptography, key handling, the sharing or escrow protocols, or autofill.

Our commitments.

Safe harbor. We will not pursue or support legal action against researchers who:

Activity conducted consistently with this policy is authorized; we consider it lawful, helpful, and appreciated.

In scope. The ZZPass iOS and macOS apps; the unreleased browser extension, whose source is public (zzpass-browser-extension), and its native-messaging host; the open-source server components (timelock-escrow, zzpass-telemetry, zzpass-monitor); and zzpass.com and its subdomains.

Out of scope — please don't report these without a concrete, demonstrated impact:

A machine-readable summary is published at https://www.zzpass.com/.well-known/security.txt (RFC 9116).

This whitepaper is a living document; it should be updated as the design evolves. Where this document and the source disagree, the source is authoritative — please report the discrepancy.