Seals 🛡️
Seals are the highest-security tier in SigNote. Each Seal is encrypted with its own unique key — completely independent from every other note. They're designed for your most sensitive information.
How Seals differ from Secrets
Secrets use a single shared session key to encrypt all bodies. That's convenient — unlock once, read everything — but it means a single key covers all your secrets.
Seals take a different approach: each note has its own Note Encryption Key (NEK), generated fresh when the note is created. Seals are never decrypted in bulk. You open one, read it, and close it. The decrypted content doesn't linger in memory.
| Secrets 🔒 | Seals 🛡️ | |
|---|---|---|
| Encryption key | One shared session key | Unique key per note |
| Decryption | All bodies on unlock | One at a time, on demand |
| Memory | All bodies in memory during session | Only the open note |
| Blast radius if key compromised | All secrets | Just one note |
How a Seal is encrypted 🔐
When you save a Seal, here's what happens cryptographically:
- A random 32-byte Note Encryption Key (NEK) is generated
- The note body is encrypted with the NEK using AES-GCM 256-bit (the note ID is used as Additional Authenticated Data)
- A seal wrapping key (
sealWrapKey) is derived from the MEK using HKDF — crucially, the note ID is part of the derivation input, making it unique to this note - The NEK is wrapped (encrypted) with
sealWrapKey, also using AES-GCM with the note ID as AAD - The encrypted body and the wrapped NEK are both stored in Postgres
The server never sees the plaintext body or the NEK.
How a Seal is decrypted
When you open a Seal:
- Derive
sealWrapKeyfrom the MEK + note ID (same HKDF derivation as during encryption) - Unwrap the NEK using
sealWrapKey - Decrypt the body using the NEK
If the note ID doesn't match the AAD used during encryption, decryption fails — this cryptographically binds the ciphertext to its specific note.
Re-encrypting after viewing
After reading a Seal, you can re-encrypt it manually using the Encrypt button. This discards the decrypted content from memory and the note returns to its locked state. It's a good habit for your most sensitive notes.
A 60-second countdown timer also re-encrypts the note automatically if you leave it open without editing.
Auto-lock 🔓
SigNote has two levels of automatic locking to protect your Seals when you're not actively using them.
Soft lock — tab hidden
When you switch away from the tab (or minimise the window), SigNote immediately clears the MEK from memory. If a Seal is open and decrypted, it is automatically re-encrypted in place — the modal stays open but returns to the encrypted placeholder view. Your deviceShare is kept in sessionStorage.
When you return to the tab and click Decrypt again, the MEK is silently reconstructed from deviceShare without asking for your passphrase. The Seal decrypts directly.
If no Seal is open, clicking Unlock on the page also re-unlocks silently.
Hard lock — inactivity or sleep
A hard lock occurs when:
- You click the Lock button explicitly
- The tab has been inactive for 5 minutes (no mouse, keyboard, or touch input)
- The device goes to sleep (detected when the tab resumes after a gap of 30+ seconds)
On hard lock:
- The MEK is cleared from memory
- The
deviceShareis cleared fromsessionStorage - Any open decrypted Seal modal is closed immediately
- All encrypted content is inaccessible until you enter your passphrase again
The AAD binding
Additional Authenticated Data (AAD) is a feature of AES-GCM. Data included as AAD is authenticated but not encrypted — if it doesn't match what was used during encryption, decryption fails with an authentication error.
SigNote uses the note ID as AAD on both the body encryption and the NEK wrapping. This means:
- A ciphertext extracted from one Seal can't be decrypted as if it were another
- Cross-note attacks require corrupting the note ID, which is detectable
Search
Seals can be searched by title only. Like Secrets, the bodies are encrypted and the server can never index them.
Technical details
- Algorithm: AES-GCM 256-bit (both for body and for NEK wrapping)
- NEK: 32 random bytes, generated fresh per note
- Wrap key: HKDF from MEK with info string
signote-v1/seal-wrap/<noteId> - AAD: Note ID (used on both body encryption and key wrapping); attachments use
seal-file:v1:<noteId> - Stored:
encryptedBody+wrappedNoteKeyin Postgres; attachment ciphertext in object storage
→ Full cryptographic details in Encryption.
→ Understanding the threat model? See Threat model.
File attachments 📎
Files attached to a Seal are encrypted in the browser with that Seal's own NEK — the same key as its body — and bound to its note ID. The server receives only ciphertext, and a file belongs to its Seal the way the body does: it can't be opened with another Seal's key, pasted into another note, or linked to one.
Uploading is blocked if encryption is locked — you must unlock first.
Moving a Secret to Seals re-encrypts its attachments under the new Seal's key as part of the move. Attachments added to a Seal before files were keyed this way are still under the account's attachment key; they move onto the Seal's own key the next time you change your encryption keys.
→ Full details in File uploads