### Security Model Napa stores all passwords in a database file. This file consists of two sections: - A unencrypted *header* that contains metadata about the database. - A encrypted *body* that contains the database entries. In [Gasti and Rasmussen (2012)](https://www.cs.ox.ac.uk/files/6487/pwvault.pdf), they propose two models for evaluating the security of password manager database formats: 1. *indistinguishability of databases*, IND-CDBA: an attacker should not be able to glean information about the password entries of the database. 2. *malleability of chosen databases*, MAL-CDBA: an attacker should not be able to modify an existing database to create a new database that the password manager accepts as valid. As described in the article, most database formats used in practice fail both of these requirements. Most formats leave some database data unencrypted (such as website URLs), and do not authenticate the database against hostile modification. Notably, `pass` fails both of these requirements, since password file names are not encrypted, and the files themselves do not use authenticated encryption. In 2020, [Weckwerth, Xia, and Zhang](https://courses.csail.mit.edu/6.857/2020/projects/16-Weckwerth-Xia-Zhang.pdf) wrote a follow-up paper and noted that most password managers are still vulnerable to these attacks. Napa avoids both of these attacks by: 1. encrypting all password entries - the only unencrypted information is in the header, which does not contain any information that is derived from the contents of the database. 2. using authenticated encryption with additional data (AEAD) to authenticate the body and header against malicious modification. With this scheme the only information exposed is the total length of the database entries, which cannot be completely hidden since the database can be of arbitrary size. As a partial mitigation Napa pads the serialized entries to a fixed blocksize before encryption to obfuscate the true length. ### Cryptographic Algorithms Napa uses several cryptographic algorithms to implement the security guarantees mentioned above. The Napa database is secured with a passphrase. This passphrase is stretched using Argon2id to derive a key. The database entries are serialized into a binary format, which is then padded using ISO 7816-4 to a fixed blocksize (currently 1 KiB). The padded entries are then encrypted using XChaCha20-Poly1305 with the derived key, using the header as additional data. ``` +------------+ Argon2id +-----+ | Passphrase | ----------> | Key | ---------+ +------------+ +-----+ | +--------+ | XChaCha20-Poly1305 +---------------+ | Header | ------+--------------------> | Database File | +--------+ | +---------------+ +---------+ ISO 7816-4 +-----------+ | | Entries | ------------> | Plaintext | ---+ +---------+ +-----------+ ``` Further details of the format of the header and body are described below. ### Header ``` +--------------+ | Magic Number | 32-bit integer, little-endian +--------------+ | Version | 32-bit integer, little-endian +--------------+ | Iterations | 32-bit integer, little-endian +--------------+ | Memory | 32-bit integer, little-endian +--------------+ | Threads | 32-bit integer, little-endian +--------------+ | Salt | 128-bit array +--------------+ | Nonce | 192-bit array +--------------+ ``` - The *magic number* is a file signature used to identify the Napa database. It is set to 0xA8F988BA. - The *version number* specifies the format of the database, and will be incremented if the format changes in a backwards-incompatible way. This document describes the database format for version 0. - *Iterations* is the number of iterations used during the Argon2id key derivation. It is currently set to 4. - *Memory* is the amount of memory in KiB used during the Argon2id key derivation. It is currently set to 1048576 (1 GiB). - *Threads* is the number of threads used during the Argon2id key derivation. It is currently set to 1 (single-threaded). - The *salt* is used to salt the passphrase during the Argon2id key derivation. A new salt is randomly generated every time the passphrase is changed. - The *nonce* is used during the XChaCha20-Poly1305 encryption. A new nonce is randomly generated every time the database is encrypted. ### Body The decrypted body of the database consists of an arbitrary number of *entries* concatenated together. Each entry consists of *key* and *value* strings that are serialized in the following way: ``` +------------+ | Key Size | 32-bit integer, little endian +------------+ | Key | UTF-8 encoded string +------------+ | Value Size | 32-bit integer, little-endian +------------+ | Value | UTF-8 encoded string +------------+ ``` Within the database, the entries are sorted alphabetically by key. Entries with the same key are sorted in chronological order.