BioVault

August 24, 2026 · View on GitHub

BioVault keeps a password vault encrypted on an NFC implant, unlockable only by the Flipper that owns it.

The encrypted vault lives on the implant. The key that decrypts it lives only in the Flipper's secure enclave and never leaves it. You need both the implant and its Flipper to read anything; possession of either one on its own reveals nothing. Read the implant using the Flipper, load the vault, and browse, edit, or type your credentials straight into a computer over USB. No external tooling, no proxmark, everything in RAM.

How it works

BioVault splits your secrets across two things you hold:

  • The implant stores the vault as one AES-256-GCM encrypted blob in Sector 1. On its own it is just ciphertext, and tampering with it is detected.
  • The Flipper holds the decryption key, wrapped by a device-unique key that is generated inside the STM32WB55 secure enclave and can never be read back out. On its own it has nothing to decrypt.

When you Load, the Flipper reads the blob from the implant, decrypts it in RAM, and shows the vault. Edits stay in RAM until you Save them back to the implant. Nothing is ever written to the Flipper's storage except the wrapped key.

Hardware

  • Dangerous Things xSIID implant, or any NTAG I2C Plus 2K implant (NXP NT3H2211).
  • The vault occupies Sector 1 only. Sector 0 (UID, NDEF records) is left untouched, so the implant still works as a normal NFC tag alongside the vault.

Features

  • Read, write, and browse an encrypted credential vault on the implant.
  • Add, view, edit, and remove credential and note entries on-device, with an extended keyboard for symbols.
  • Secrets and notes up to 255 characters per entry, enough for a 24-word seed phrase, with the vault compressed before encryption to make the most of the implant's 1 KB.
  • Send a username, password, or note to a computer over USB-HID, with an optional trailing Return.
  • Optional implant password protection, so the implant itself refuses reads without a device-bound password (see Implant protection).
  • Optional 6-digit vault PIN wrapping the vault key with PIN-derived key material (see Vault PIN).
  • A biovault USB serial CLI that mirrors every on-device command, so you can manage the vault and add or copy passwords from a terminal.

Usage

The app opens on Load from Implant (after the PIN screen, if a vault PIN is set); hold the implant to the Flipper, then it drops into the main menu:

Menu itemWhat it does
VaultBrowse entries; open one to View, Send (USB-HID), Edit, or Remove it.
Add EntryAdd a credential (label + username + password) or a note (label + text).
Load / Read / Save / Wipe ImplantSync the vault to and from the implant. Load first, so Save never overwrites the implant with an unsynced vault.
SettingsUSB auto-return, implant password protection, vault PIN.
About / DiagnosticsUsage notes and crypto self-test results.

CLI

Connect over USB serial, run biovault to open a subshell, and use:

Vault:    list, get <label>, add <label>, edit <label>, remove <label>
Device:   read, load, save, wipe, reveal
Protect:  protect, unprotect        (confirmed on the Flipper)
Config:   settings [<key> <value>], pin <set|remove|enter>

reveal prints the implant's password to the terminal (handy for a Proxmark), but only after the provisioned implant authenticates.

Security model

The design goal is that your data stays safe even if you lose the Flipper, because the vault is never stored on the Flipper, only on the implant.

ScenarioWhat the attacker hasOutcome
Lost or stolen Flipper (even unlocked)The wrapped key, but no dataNothing exposed. The enclave key is gone, so the vault becomes unrecoverable. A recoverability loss, not a confidentiality loss.
Implant read over NFCThe ciphertext blobUseless without your Flipper's enclave key, which can't be cloned to another device. With implant password protection enabled they can't even read the blob.
keystore.bin copied off the SD cardThe wrapped vault keyDoesn't matter. The wrap can only be undone inside this Flipper's enclave (and needs the PIN too, if set), so the file is useless on any other hardware.
Your Flipper and NFC range to your implantBoth factorsThe only real exposure, and with a vault PIN set they still need that too.

The Flipper is not a hardened secure element, and it does not need to be here: it never holds the plaintext vault at rest, only transiently in RAM while the implant is coupled. Keeping the data off the Flipper is what makes a lost device a non-event for confidentiality.

Vault PIN (optional)

Settings → Vault PIN (or pin set in the CLI) wraps the vault key under a 6-digit PIN. This is key material, not a check: there is no PIN verification anywhere in the code to patch out, and no verifier stored on the Flipper. A stolen Flipper alone gives an attacker nothing to even test PIN guesses against. If they also obtain the implant's ciphertext, every guess must still run a multi-second key-stretching chain through this Flipper's secure enclave (PBKDF2 plus ~16k enclave AES iterations, about 3 seconds per guess), which cannot be offloaded to faster hardware: sweeping all 10610^{6} PINs costs about a month of continuous on-device grinding. Guessing through a read-protected implant instead runs into its auth limit, which locks the implant when hit.

The trade-offs of having no verifier:

  • A wrong PIN cannot be detected at entry. It just derives the wrong key; loads then fail authentication ("wrong PIN?").
  • With read-protection enabled, a wrong-PIN session presents a wrong implant password, which burns one of the implant's failed-auth attempts per load if an auth limit is set. Keep the auth limit high, or off, when using a PIN.
  • A forgotten PIN loses the vault. There is no reset that doesn't destroy the security. Removing the PIN is only allowed once the session is proven safe: after a load that decrypts the vault (proving the PIN), or after a load of a blank implant or a wipe (no ciphertext left to orphan).

Backups and firmware updates

Two things must survive for the vault to keep working: the wrapped-key file on the SD card (apps_data/biovault/keystore.bin) and the enclave key, which is generated on-device by the hardware TRNG and lives in the STM32WB55's secure storage. There is no recovery path for the enclave key.

EventKeystore file (SD)Enclave keyVault
Official firmware updatesurvivessurvivesfine
Custom firmware, or switching firmwaresurvivessurvivesfine
Radio stack (CPU2) updatesurvivessurvivesfine
SD card formatted, corrupted, or replacedlostsurvivesrestore keystore.bin from a backup
Coprocessor secure storage wiped, or hardware failuresurvives (useless)lostgone, by design

Backing up keystore.bin to a computer is safe and recommended: as the threat table above notes, the file is useless off-device. A backup protects against SD card loss only.

Implant protection (chip-side)

Beyond the encryption, you can optionally enable the NTAG I2C Plus's own hardware protection, so the implant itself refuses access to Sector 1 without a password. It is opt-in from Settings → Protect implant and fully reversible (Unprotect implant).

The NT3H2211 offers several protection mechanisms. BioVault uses them like this:

MechanismRegisterHow BioVault uses it
Password authenticationPWD_AUTH / PACK32-bit password and 16-bit acknowledge, both derived from the enclave key and the implant UID: device-bound, unique per implant, never stored. The PACK the implant returns is verified on every unlock, so a cloned or emulated implant that merely spoofs the UID still can't authenticate.
Sector 1 gate2K_PROTGates all of Sector 1 (the vault) behind the password. The core of the feature.
Read vs write protectionNFC_PROTThe Read protect setting chooses whether the password guards writes only (ciphertext stays readable but can't be altered or cloned) or reads and writes (ciphertext can't even be read off the implant).
Failed-attempt lockoutAUTHLIMThe Auth limit setting caps failed unlocks; after 2^n failures the protected area locks permanently. Powerful but destructive: a low value can brick the implant. Off by default, and the app warns before you set it.
Protection start pointerAUTH0Left at the factory value (0xE2), which keeps the implant's own configuration pages (password and access bytes) behind the password while leaving Sector 0 user memory / NDEF open.

BioVault deliberately does not touch the implant's one-way locks. It never sets REG_LOCK (which would permanently freeze the configuration registers), the static / dynamic lock bits, or NFC_DIS_SEC1 (which would cut Sector 1 off from NFC entirely). Avoiding those is what keeps provisioning reversible: Unprotect restores the implant to its factory-open state.

The xSIID ships pre-configured with AUTH0 = 0xE2 and the well-known Dangerous Things password (DNGR) guarding only its configuration pages, with Sector 1 open, which is why the vault works before provisioning. BioVault authenticates with that factory password the first time it protects an implant, then replaces it with the device-bound one.

On-implant format

Sector 1 blob    : [magic 'BV':2][ver:1][nonce:12][ct_len:2 LE][ciphertext][tag:16]
Flipper keystore : [magic 'BVK1':4][wrap_iv:16][wrapped_dek:32]
        with PIN : [magic 'BVK2':4][salt:16][sw_iters:4][hw_iters:4][wrap_iv:16][wrapped:32]

(The trailing tag:16 is the AES-GCM authentication tag, not the NFC tag.)

The blob plaintext is heatshrink-compressed before sealing. In the keystore, wrapped is the data key, XORed with the PIN-derived key (when a PIN is set) before the enclave wrap.

A keystore that exists but doesn't parse (a torn write or SD corruption) is refused rather than re-keyed, so a glitch can't orphan the on-implant vault.

Building

Built with uFBT:

ufbt            # build -> dist/biovault.fap
ufbt launch     # build, upload, and run on a connected Flipper

License

MIT, see LICENSE.