Skip to content

Device Security & Backups

PIN Protection

The app is protected by a user-chosen PIN, verified using a deliberately slow hashing algorithm to resist brute-force attacks.

How PIN Hashing Works

ParameterValue
AlgorithmPBKDF2-SHA256
Salt16 bytes, cryptographically random
Iterations10,000 (v2 format)
Output32-byte derived key
Storagev2:<iterations>:<salt_hex>:<hash_hex> in SecureStore

The PIN is never stored in plaintext. On verification, the entered PIN is hashed with the stored salt and compared using a constant-time comparison to prevent timing side-channel attacks:

typescript
function timingSafeEqual(a: string, b: string): boolean {
  if (a.length !== b.length) return false;
  let diff = 0;
  for (let i = 0; i < a.length; i++) {
    diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
  }
  return diff === 0;
}

Legacy Migration

Earlier versions used 600,000 PBKDF2 iterations (v1 format). On successful verification of a v1 PIN, the hash is automatically migrated to v2 format. This is transparent to the user.

In plain English: Your PIN is never stored as-is. Instead, it goes through a slow mathematical process that produces a fingerprint. When you enter your PIN, the app runs the same process and checks if the fingerprints match. The process is designed to be slow enough that trying millions of PINs would take an impractical amount of time.


Biometric Unlock

Biometric authentication (Face ID / Touch ID / fingerprint) can be enabled as an alternative to PIN entry. When enabled:

  • The biometric preference is stored as a flag in SecureStore.
  • The OS handles the actual biometric matching — Relay never accesses biometric data directly.
  • Biometric unlock can be skipped during setup; PIN remains the fallback.

Auto-Lock

The app automatically locks when backgrounded, requiring PIN or biometric authentication to resume. The lock timing is configurable:

SettingBehavior
Every timeLocks immediately when app goes to background
After 1 minuteLocks if backgrounded for more than 60 seconds
After 5 minutesLocks if backgrounded for more than 5 minutes
After 15 minutesLocks if backgrounded for more than 15 minutes
After 1 hourLocks if backgrounded for more than 1 hour
NeverApp does not auto-lock

The lock state is tracked using AppState listeners. When the app returns to the foreground, the elapsed background time is compared against the configured threshold.


Encrypted Backups

Relay provides a local encrypted backup system for your seed phrase and message history. Backups are encrypted on-device before being saved to local storage.

Backup Pipeline

Encryption Details

ParameterValue
Key derivationArgon2id
Argon2 iterations3
Argon2 memory64 MB
Argon2 parallelism1
Output key length256 bits
EncryptionAES-256-GCM
IV length12 bytes (random)
Salt length16 bytes (random)

Binary Format

The backup file uses a custom binary format:

RELAY_BACKUP_V1 file layout:

Offset   Length   Contents
0        16       Magic bytes: "RELAY_BACKUP_V1\0"
16       16       Argon2id salt (random)
32       12       AES-GCM IV (random)
44       variable Ciphertext + GCM auth tag

File extension: .relaybackup

Round-Trip Verification

Before saving, the backup is immediately decrypted and compared byte-for-byte against the original data. If they do not match, the backup is rejected. This prevents saving corrupt backups that would fail on restore.

Backup Scope

Users control what gets included in the backup:

ToggleContents
Seed phraseThe 12-word BIP39 mnemonic
Text messagesAll conversation message history
Voice messagesVoice recordings (planned)
MediaPhotos and attachments (planned)

Backup Password

The backup password is used only at encryption and decryption time. It is:

  • Never stored in plaintext — only a "has been set" marker is saved.
  • Held in memory only for the duration of the backup/restore operation.
  • Separate from the PIN — it can (and should) be different.

In plain English: When you make a backup, you choose a password. That password is run through a very hard-to-crack process (Argon2id, which deliberately uses a lot of memory and CPU) to produce an encryption key. Your data is then encrypted with that key and saved as a file. The password is not saved anywhere — if you forget it, the backup cannot be opened. Before saving, the app double-checks by decrypting the backup to make sure it is not corrupted.


Server Trust Model

The server is designed to hold the absolute minimum data required to deliver encrypted messages. Everything else stays on your device.

What the Server Never Sees

This is the important list — the data that never leaves your device under any circumstances:

DataWhy it stays on-device
Wallet private keySelf-custodial — funds cannot be moved without it
Auth private keyOnly the signature is sent, never the key itself
Wallet addressNever exposed to the server, other users, or any API
Seed phraseThe root of all key material — exists only in device secure hardware
Plaintext messagesEncrypted before they leave the device; decrypted only on the recipient's device
PIN or biometric dataVerified entirely on-device by the OS
Signal session stateRatchet keys, chain keys, skipped message keys
Backup passwordsUsed transiently during backup/restore, then discarded from memory
Message historyMessages are automatically purged from the server on delivery

What the Server Does Hold

Only what is strictly necessary for a messaging relay to function:

  • Username and auth public key — needed to route messages and verify login signatures.
  • Signal pre-key bundles (public parts only) — needed so a new contact can establish an encrypted session with you.
  • Encrypted ciphertext in transit — held temporarily until the recipient's device acknowledges delivery, then automatically purged.

That is all. The server does not retain message history, does not store wallet addresses, and does not maintain a social graph.

What a Full Server Compromise Would Reveal

If an attacker gained complete access to the Relay server and database, they would find:

  • A list of usernames and auth public keys (public information by design).
  • Signal pre-key bundles (public keys only — useless without the corresponding private keys).
  • Any messages currently in transit (encrypted ciphertext, unreadable without the recipient's on-device private keys).

They would not be able to read any message, access any wallet, impersonate any user, or recover any seed phrase. Forward secrecy means that even recording all traffic and later compromising a key would not decrypt past messages.

In plain English: If someone hacked the Relay server and stole everything, they would get a list of usernames and a small number of encrypted messages waiting to be delivered. They could not read those messages, log in as you, or touch your money. There is no message archive to steal because messages are deleted as soon as they are delivered.

Built with conviction.