Security

How PrivaLog protects your diary

Last updated: October 14, 2026

The short version

Your entries are encrypted on your device. Without an account, your diary stays on that device and nothing from it is sent to us. With an account, entries reach us only in encrypted form. The key that opens them is locked with a passphrase that only you know, and that passphrase never leaves your device. We store that diary, but we cannot read it. If you lose your passphrase, nobody can get those entries back, including us.

PrivaLog is not open source. This page is how we document what the code does instead. It describes the iPhone, iPad and Mac apps and the web app as they work today.

What happens on your device

The diary key

When you start a diary, the app creates a diary key: a random 256-bit number that encrypts and decrypts your entries. Entries are encrypted with AES-256-GCM, a widely used encryption method. It also detects tampering: if an encrypted entry is changed, the app refuses to open it instead of showing altered text.

A diary without an account

If you start writing without an account, there is no passphrase. The diary key is stored in the Keychain on your device, and the diary opens the way you unlock your device: with Face ID, Touch ID or your device passcode. That is a lock in the app, not a second key: anyone who can unlock your device can open the diary. On a device without a passcode, the diary does not lock. Nothing from your diary is sent to us. The key is not tied to this one device, so an encrypted backup of your iPhone or iPad, in iCloud or on a computer, contains your diary and its key. How well that backup is protected depends on Apple: an iCloud backup is end-to-end encrypted only with Advanced Data Protection. We never get a copy.

The passphrase

When you create an account, you choose a diary passphrase of at least 8 characters. The app turns it into a second key with Argon2id, a method built to make each guess slow and memory-hungry. That second key locks your diary key. Only the locked diary key is sent to us. When you unlock, your device downloads the locked key and does all the work itself. Your passphrase is never sent to us. If you already wrote without an account, your diary keeps the same diary key: the passphrase locks it, and your entries move into your account. From then on the key on your device is no longer in device backups; on a new device you use your passphrase.

What is encrypted

Everything you write in an entry is encrypted together: the title, the text, your mood, tags, the favorite mark, and places, including their coordinates. The date of an entry is not encrypted. See What our servers store.

Face ID, Touch ID and passcode

With an account, your diary opens with your passphrase or with Face ID or Touch ID. On a device that has Face ID or Touch ID, it is turned on when you create your passphrase or merge a diary into your account, unless you chose otherwise before. You can turn it off in Settings. The app then stores the diary key, not your passphrase, in the Keychain. That copy stays on this device, is not included in backups, and can only be read after Face ID or Touch ID succeeds. The device passcode is not enough, so someone who has seen you type it still cannot open your diary. On a device without Face ID or Touch ID, you can choose to unlock with the device passcode instead. The system checks your face or fingerprint; PrivaLog never receives it. If you add or remove a face or fingerprint, the stored key stops working and you unlock once with your passphrase.

How long the diary stays open

After you unlock, the diary key stays in the app's memory until the diary locks. That happens when you lock it yourself, sign out or close the app, and when PrivaLog has been in the background for the time you choose in Settings: immediately, after 1, 5 or 15 minutes, after an hour, or never. The default is 1 minute on iPhone and iPad and 5 minutes on Mac. On a Mac the diary also locks as soon as the screen locks or goes to sleep, unless you chose Never. While the app is in the background, its screen is covered, so the app switcher does not show your entries. Signing out deletes the stored key from the Keychain. The encrypted copies of your entries stay on the device, so you don't lose entries that have not synced yet.

Search

Search runs on your device, over entries that are already decrypted in memory. No search index is written to disk or sent to us.

What our servers store

This applies to accounts. A diary without an account never reaches our servers. We use Supabase for accounts and storage. Our Supabase project is hosted in the EU, in Ireland. Each account can only reach its own rows; the database enforces this.

Email address and account ID
Why: To sign you in and link your data to you
Can we read it? Yes
Sign-in details: a password, or your Sign in with Apple identity
Why: To sign you in
Can we read it? We can see which method you use. A password is kept by Supabase in hashed form, not as readable text.
Encrypted entries
Why: To sync your diary between devices
Can we read it? No
Entry dates
Why: To find and sync each entry. There is at most one entry per day.
Can we read it? Yes
Created and updated times, version numbers and technical fields needed to decrypt
Why: To sync and to resolve conflicts
Can we read it? Yes. They say nothing about what you wrote.
Locked diary key
Why: So you can unlock on another device
Can we read it? No. It is encrypted with a key that only your passphrase can produce.
Unlock check
Why: So the app can tell whether a passphrase is right
Can we read it? No. It is a short known text encrypted with your diary key. It shows whether a key is correct, not the key itself.
Salt and Argon2id settings
Why: So every device turns your passphrase into the same key
Can we read it? Yes. They are not secret.
Settings: language, theme, timeline display
Why: So they follow you to other devices
Can we read it? Yes
When you accepted the terms and acknowledged the passphrase and backup warnings
Why: As a record of your agreement
Can we read it? Yes
Trial and subscription status, and the Apple transaction ID of a purchase
Why: To know whether cloud sync is active
Can we read it? Yes

In short: we can see that you have an account, your email address, on which days you wrote and when. We cannot see what you wrote.

Cloud sync needs an active trial or Pro. Without it, new entries stay on your device and are not sent to us. Entries that were synced before stay stored, encrypted, until you delete them or your account. The locked diary key and the unlock check are stored for every account.

When you delete your account, your account, entries, locked key and subscription status are deleted from our database straight away. Copies may remain in our providers' backups for a limited time. Purchase records kept by Apple and RevenueCat are not deleted by this.

Account password and diary passphrase

With an account, PrivaLog uses two separate secrets. They do different jobs.

  • Your account password (or Sign in with Apple, or an email link) proves to our server who you are. You can reset it by email. Resetting it does not open your diary.
  • Your diary passphrase locks your diary key. It never leaves your device, we never see it, and nobody can reset it.

Your account password is sent over an encrypted connection to sign you in, as on any website. Your diary passphrase is not sent at all. Use a different value for each.

Services we use

Supabase
What it is for: Accounts and encrypted storage
What it sees: Everything listed in the table above, plus IP addresses
Vercel
What it is for: Hosts this website and the web app
What it sees: IP addresses and the pages requested. When you sign in on the web, your account password passes through it to Supabase. Page-view statistics on the home page only, without cookies (Vercel Web Analytics).
RevenueCat
What it is for: Pro subscription status in the apps
What it sees: When the app starts, a random ID that RevenueCat creates, plus technical data such as your IP address and the app and system version. With an account, also your account ID, which is a random identifier, and your purchases. Never your email address or your entries.
Apple
What it is for: App Store, payments and Sign in with Apple
What it sees: Your purchases, and your Apple ID if you use Sign in with Apple. Nothing from your diary.
Apple Maps
What it is for: Place search and current location in the apps, only when you add a place
What it sees: Your search text, or your location when you use current location
OpenStreetMap Nominatim
What it is for: Place search in the web app, only when you add a place
What it sees: Your search text and your IP address
jsDelivr
What it is for: Emoji images in PDF exports from the web app
What it sees: Which emoji appear in the exported entries, and your IP address

The place you pick is stored only inside the encrypted entry. The apps and the signed-in web app contain no analytics or advertising code.

Offline

  • iPhone, iPad and Mac: you can read and write without a connection. New and changed entries are encrypted first, kept on the device, and sent when you are back online, if cloud sync is active.
  • Web: the web app needs a connection to open. If it is already open and the connection drops, entries you save are encrypted and kept in the browser until you are back online. Writing on the web needs an active trial or Pro.

Offline copies are encrypted in the same way as the copies on our servers.

The web version

The web app encrypts in your browser, with the same method and settings as the apps: AES-256-GCM through the browser's built-in Web Crypto, and Argon2id through a WebAssembly library.

There is one important difference. An app from the App Store is signed and checked before it reaches you, and it stays the same until you update it. The web app is sent by our server every time you open it. If that server sent altered code, that code could read your passphrase as you type it. When you use the web version, you trust us and our hosting provider on every visit.

Some measures limit this, but do not remove it. The site is served only over HTTPS. A Content Security Policy lets pages connect only to our own site and the services listed above, and load images only from our own site. It does allow inline scripts, which the site's framework needs. We do not use Subresource Integrity.

After you unlock, the web app keeps your diary key in the browser's storage, in a form that the page can use but cannot read or copy. The tab can use it until you lock the diary, sign out, or close the tab. There is no automatic timeout. Signing out removes all stored keys, but leaves the encrypted copies of your entries in the browser.

If you want the stronger model, use the iPhone, iPad or Mac app.

If you lose your passphrase

There is no reset and no recovery. We do not have your passphrase or your diary key, so we cannot open your diary for you, and neither can anyone else. This is on purpose: a way in for us would also be a way in for others. Without the passphrase, your entries cannot be read again. You can delete your account and start a new one.

  • Store your passphrase somewhere only you control, such as a password manager or a written note kept somewhere safe.
  • Face ID and Touch ID do not replace it. You need the passphrase on a new device, after signing out, and after a face or fingerprint is added or removed.
  • If a device is still unlocked, you can still export a readable copy from it. Treat that file like the diary itself.
  • A diary without an account has no passphrase. It exists only on that device and in its backups. If you lose the device and have no backup, the diary is gone; we have no copy.

What PrivaLog does not protect against

  • Someone using your device while the diary is open, or an open browser tab. In the apps the diary stays open until it locks, as described above.
  • Someone who knows your device passcode, if you write without an account. That diary opens the way your device unlocks.
  • Malware, a malicious browser extension or keyboard on your device. It can see what you see and type.
  • Someone who knows your passphrase. Changing the passphrase does not change the diary key itself, so someone who knew the old passphrase and kept a copy of the old locked key could still read your entries.
  • A weak passphrase. Anyone with a copy of our database could try to guess it offline. Argon2id makes each guess slow, but a short or common passphrase can still be found.
  • Metadata: your email address, the days you wrote on, when entries were created and changed, how many there are, your subscription status, and IP addresses in our providers' logs.
  • Readable exports. PDF, Markdown, KML and readable JSON files are plain text. Anyone who gets the file can read it. Encrypted backups are not readable without your diary key.
  • Screenshots, copied text and anything else that leaves the app.
  • Altered code sent to the web app, as described above.
  • A server that holds back data. It cannot change an entry without the app noticing, or move it to another day or account. It could delete entries, or return an older version of an entry.
  • Searches and locations you send to Apple Maps or OpenStreetMap when you add a place.

Technical details

Entries

  • AES-256-GCM with a 96-bit nonce and a 128-bit authentication tag. A new random nonce is generated for every encryption; nonces are never reused on purpose.
  • The plaintext is a JSON object with the entry fields. Additional authenticated data binds each ciphertext to its account, entry and date: {"v":1,"user_id":…,"entry_id":…,"entry_date":…,"crypto_schema_version":…}

Keys

  • Diary key (DEK): 256 bits from the system's secure random generator.
  • Key-encryption key (KEK): Argon2id(passphrase, salt). The salt is 128 random bits.
  • Argon2id version 1.3 (0x13), memory 65,536 KiB (64 MiB), 3 iterations, parallelism 1, 32-byte output. The same on every platform. The settings are stored per account.
  • Key wrapping: AES-256-GCM encryption of the DEK with the KEK, with its own random 96-bit nonce and no additional data.
  • Unlock check: AES-256-GCM encryption of a fixed text with the DEK, with its own random nonce.
  • Changing the passphrase creates a new salt and KEK and wraps the same DEK again. Entries are not re-encrypted.
  • Diaries created before key wrapping was introduced use the Argon2id output itself as the DEK. It is stored wrapped in the same format.

Libraries

  • iPhone, iPad and Mac: Apple CryptoKit for AES-GCM; Argon2Swift on the Argon2 reference implementation (phc-winner-argon2); the Security framework for random bytes and the Keychain; LocalAuthentication for Face ID and Touch ID.
  • Web: the Web Crypto API for AES-GCM and random bytes; hash-wasm (WebAssembly) for Argon2id.

Storage on the device

  • Account diary with Face ID or Touch ID unlock: a Keychain item that is readable only while the device is unlocked (kSecAttrAccessibleWhenUnlockedThisDeviceOnly), never synced or restored to another device, and only after Face ID or Touch ID succeeds (biometryCurrentSet). On devices without biometrics, the device passcode can be chosen instead (userPresence).
  • Diary without an account: the DEK is a Keychain item that is readable while the device is unlocked (kSecAttrAccessibleWhenUnlocked), without access control, so it is included in encrypted device backups. Before it opens the diary, the app asks for Face ID, Touch ID or the device passcode (deviceOwnerAuthentication). Entries use the same format, with the diary's random ID in the user_id field.
  • Moving into an account: every entry is decrypted, encrypted again with the account ID in the additional authenticated data, and checked by decrypting it before upload. With a new account the DEK stays the same; when you merge into an existing account, entries are encrypted with that account's DEK. Local data is deleted only after every entry is confirmed and every day with an entry in both places is resolved.
  • Offline copies: ciphertext only, in the app's own storage on Apple devices and in IndexedDB in the browser.
  • Web session: the DEK is a non-extractable Web Crypto key in IndexedDB; sessionStorage holds only a random ID for the tab. Keys from tabs closed without locking stay until the next unlock or sign-out in that browser.

Server

  • Postgres row-level security limits every table to the rows of the signed-in account.
  • All connections use HTTPS. This site sends a Strict-Transport-Security header.

Reporting a security issue

If you find a security problem, email privacy@nextdevstudio.com. Please include the steps to reproduce it, and give us a reasonable time to fix it before you publish details.

Last updated

October 14, 2026. When we change how encryption, storage or outside services work, we update this page. See also the Privacy Policy.

Back to home