Skip to content
The world does revolve around you.

Encryption#

This page explains how Ostler protects your data on disk, in memory, and on the wire between the Hub and the iOS app. It is written for readers who want enough detail to make a judgement about the design, not for readers looking for a copy of our cryptographic specification. The latter exists, it is locked, and it is being prepared for the independent auditor.

The short version: standard primitives, applied conservatively, with no novel cryptography on the critical path. The deepest security property of Ostler is that there is no network connection to begin with – the encryption is the second line, not the first.

Honest status labels

Throughout this page, encryption layers are labelled with one of three statuses: Live (in shipping code today), In development (specified, partially built, on the launch path), or Planned (on the post-launch hardening list). The marketing Security page carries the same labels, line for line. We update these together.

What we are protecting#

The Hub holds derivative data extracted from your messages, your contacts, your calendar, your browsing history. That derived knowledge graph is, in some ways, more sensitive than the raw inputs – it is the synthesis. Encryption at rest is therefore not optional. The threat model that drives the design is:

  • Lost or stolen Mac, attacker with physical access.
  • Backup theft (Time Machine drive lifted, cloud backup of the wrong file).
  • Other software on the same machine with file-system access but not the user's interactive session.

The model does not claim to defend against malware that has fully compromised your user account while you are logged in and unlocked. That is a different problem and we are honest about it on the marketing Security page.

Layers of encryption at rest#

Encryption at rest is layered. Each layer is independent of the others, and each protects against a different failure of the layer above.

Layer 1: macOS FileVault – Live#

Your entire disk, including every byte Ostler writes, sits inside a FileVault volume. FileVault is Apple's full-disk encryption: AES-256 in XTS mode, key tied to your Mac's hardware. The installer checks that FileVault is enabled and warns you if it isn't.

This is the layer that protects against the "stolen Mac at the airport" case. Without your login, the disk is ciphertext.

Layer 2: SQLCipher for the relational databases – Live#

Ostler's structured data – the conversation pipeline state, the identity-resolution decisions, the audit log – lives in SQLite databases, each one encrypted by SQLCipher (AES-256). SQLCipher is the standard, audited extension to SQLite that adds full-database encryption. This is the same library that protects Signal Desktop's local store, among many others.

The key that unlocks these databases is derived from your install-time passphrase, with the Secure Enclave's biometric-gated PRF output as the unlock factor (see Authentication and key handling below). When Ostler is locked, that key is wiped from memory. The databases on disk are ciphertext.

Layer 3: iOS app secure store – Live#

The Ostler iOS app uses Realm with AES-256 encryption for its local secure store. Today, the iOS app's voice-profile and identity material live there, with the encryption key bound to the device.

Layer 4: iOS app main store passkey-bound – In development#

The next iOS workstream extends Realm encryption across the full iOS app data store, with the encryption key derived from the same passkey path that the Hub uses. The cross-platform specification is signed off; the iOS-side pairing flow and key-derivation work is underway.

Layer 5: vector and graph stores on an encrypted volume – In development#

The vector store and graph store hold semantic embeddings and structured triples derived from your data. Today they sit inside the FileVault-protected volume. The next installer step adds a dedicated encrypted APFS volume for these stores, so an attacker who somehow gained read access to the unprotected portion of the disk would still not see them in plaintext.

Layer 6: encrypted Time Machine backups – Live#

Time Machine inherits FileVault's encryption when the source volume is encrypted. We strongly recommend enabling Time Machine encryption on the destination as well. The installer's "next steps" page reminds you.

Authentication and key handling#

The user-facing model is three things: a passphrase you set at install, biometrics for daily unlock, and a recovery key for the worst case. The cryptographic plumbing under those names is what this section describes.

What you set up – Live#

At install, Ostler asks you to choose a passphrase (minimum 16 characters or four words). That passphrase is what protects your data on disk. It never leaves your Mac, never reaches Creative Machines, and is not stored in plain text anywhere – the installer derives a key from it and discards the passphrase itself.

Biometric unlock – Live#

Day-to-day unlock is biometric: Touch ID, Face ID, or a double-click on your Apple Watch. Under the hood Ostler registers a WebAuthn passkey against your Mac's Secure Enclave via Apple's AuthenticationServices framework, using the platform authenticator's PRF extension. The biometric tap releases the passkey, the passkey unwraps the data-encryption key, the key decrypts your stores. You never see the passkey directly.

The cryptographic proof of identity lives inside your Mac's hardware security chip. It cannot be exported, phished, or copied to an attacker's machine. We never see a password because there is no password to see.

Key derivation – Live#

Ostler uses HKDF-SHA256 to derive distinct keys for distinct purposes. Domain-separation strings live in a creativemachines/ namespace – tied to the company domain, not the product name, so a future product rename cannot invalidate existing users' credentials.

There is no PBKDF2 on the primary path, because the PRF output from the Secure Enclave is already a full-entropy key. Adding a second KDF on top of full-entropy input would not increase security; it would just add complexity.

Key wrapping – Live#

Each encrypted store has its own 32-byte data-encryption key (DEK), generated locally at install time. The DEK is wrapped (encrypted) under a key derived from your passphrase plus the Secure Enclave's PRF output, using AES Key Wrap (RFC 3394, unpadded variant). A wrong unwrapping key produces an integrity failure rather than garbage plaintext.

Wrapped DEKs are stored in macOS Keychain with accessibility flags that keep them on the local device only – they do not travel in Migration Assistant or in Time Machine to a different Mac.

Memory handling – Live#

The long-lived session key Ostler holds while unlocked is kept in a mutable buffer that is explicitly zeroised on lock or auto-lock timeout. We are honest in our internal documentation about which short-lived copies in higher-level Python code we can guarantee zeroise and which we treat as best-effort. Best-effort is not a weakness in this threat model – the attacker who can read live process memory has already won at a different layer – but it is worth being precise about.

Auto-lock – Live#

Ostler auto-locks after a configurable period of inactivity, with a sensible minimum. On lock, the in-memory keys are wiped. A stolen Mac sitting on the attacker's desk cannot yield plaintext data without a live Touch ID or Face ID from you.

The recovery phrase#

There is exactly one fallback for "lost all my Apple devices and iCloud Keychain hasn't restored my passkey to a new device": a 12-word recovery phrase generated during setup.

  • The phrase is shown to you once, on a screen that blocks copy-paste, and is never stored on disk afterwards.
  • The wordlist is the publicly-audited 2048-word English wordlist popularised by BIP39. We use it because it is auditable, not because Ostler is interoperating with anything cryptocurrency-related.
  • The phrase encodes 128 bits of native entropy plus a checksum word.
  • The 16 bytes of entropy feed HKDF-SHA256 to derive an independent recovery key – a second wrap of the same DEK, separate from the passkey-bound wrap.

We do not implement BIP39's PBKDF2 mnemonic-to-seed step. A second KDF over already-full-entropy input would add no security and several ways to get it wrong.

Treat the recovery phrase like a Yale key

Write it on paper. Keep it somewhere safe. Do not photograph it, paste it into a cloud notes app, type it into a password manager, or read it out loud on a video call. If you do any of those, the phrase becomes the attacker's shortest path. If you lose the phrase and all your Apple devices and your Time Machine backup, your data is gone – by us, by anyone. That is the price of an architecture where we cannot read your data even if we wanted to.

Hub-to-iPhone transport#

Day-to-day traffic between the Hub and the iOS app is HTTP over TLS with a self-signed certificate generated on the Hub during installation. The iOS app pins the certificate's public key at pairing time. Only your Mac can answer for that pinned key.

There is no unpinned HTTP fallback. There is no application-layer bypass channel. The iOS app either has a working TLS connection to the Hub it pairs with, or it does not connect.

The pairing handshake itself is a normative cross-platform specification – every constant, every wire-format byte, every test vector is fixed. That specification is what the independent auditor will review against the implementation on both platforms.

Audit log#

Ostler keeps a local audit log of security-relevant events (unlocks, lock-outs, configuration changes, recovery operations). The log lives inside its own SQLCipher database with an event-type allowlist, query-limit clamping, and a concurrent-writer lock.

Per-entry HMAC integrity chaining – so an attacker who tampered with a historical log row would leave a detectable break in the chain – is on the planned post-launch hardening list. Today's audit log is already protected by the SQLCipher encryption layer; the HMAC chain is hardening, not the load-bearing protection.

What we deliberately did not do#

A few choices we made by not doing something:

  • No custom cryptography on the critical path. Every primitive on this page – AES-256, HKDF-SHA256, AES Key Wrap, TLS – is a standard primitive available in Apple's frameworks and audited libraries. We are not inventing.
  • No vendor-side key escrow. We do not hold a copy of your encryption key "in case you forget your passkey." If we did, the whole local-first guarantee would fall apart.
  • No "share with support" payload. When you contact us, we do not have a button that uploads your encrypted databases to us for diagnosis. We answer questions in words.

Why this design rather than something cleverer?#

The architecture is intentionally simple. The primary security mechanism – not having a network connection at all – is doing most of the work. The encryption layer is there to handle physical and local threats once that primary mechanism has done its job.

Simple cryptography has the property that it is easier to audit, easier to replace if a primitive is later weakened, and easier to explain to a security-conscious user without hand-waving. We will take all three of those over a more elaborate design every time.

Independent audit#

We are commissioning an independent security audit from a recognised cybersecurity firm. The scope covers authentication, data handling, storage encryption, network posture, and dependency analysis. The report will be published on the marketing Security page when it is complete.

We chose a professional audit over relying on community code review because an expert review is more rigorous than hoping someone reads the code. Trust should be verifiable, not assumed.