There is no such thing as an absolute measure for software security. Software is designed to resist specified attack vectors under a range of conditions. It also depends on the user choices, like who they share information with or how strong the passwords they use are, and on factors outside of the developer control, like vulnerabilities on the operating system or the hardware itself. It's your responsibility to read this document and the End User License Agreement, understand how security is approached in PaperVault, and decide if the application is adequate for your intended usage.
PaperVault was written with the goal of handling sensitive information. PaperVault follows the principle information at rest should be securely encrypted using a secret only known to the user. This includes both the documents stored on the application itself in the user's device, and the printed documents. It's important to note there is no recovery mechanism for documents either stored on the device or printed. If the user forgets the password, the data is considered lost.
All the encryption algorithms are implemented by Apple CryptoKit framework, which is part of Apple operating systems. PaperVault uses CryptoKit APIs to perform encryption, decryption and related security activities.
This application does not use the network, does not perform any network requests nor does it store data in any cloud service. Data is encrypted and encoded on the printed QR Codes themselves. Per the normal behaviour of the operating system, encrypted data may still travel across the network when backed up and printed to networked printers. See the Network section for more details.
As a quick overview, each document is encrypted with a document-specific key. The key is itself encrypted with a global key, and stored in the file system. The global key is generated during the app initial setup, encrypted by a key derived from the main password provided by the user, and also stored in the file system.
During the initial setup, a random 256-bit key is generated. This is the global file encryption key. To protect that key, a temporary key is derived from the main password the user provides. The derivation of that temporary key is done through the following algorithm, using a random 128-bit salt and 10 million derivation rounds:
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
passwordPtr, strlen(passwordPtr),
saltBuf.baseAddress!.assumingMemoryBound(to: UInt8.self),
saltBuf.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
rounds,
&output, output.count)
The global encryption key is then encrypted (wrapped, using AES.KeyWrap) by the temporary key, and stored on the file system, together with the salt and number of derivation rounds. The temporary key is discarded. This means the only way to obtain the key necessary to unwrap the global key is performing a similar derivation of the temporary key from the main password, the saved salt and number of rounds.
During app setup (and any time when changing the main password) the user may choose to store the main password in the device keychain. This is only possible if the user has configured authentication on the device (like Face ID or Touch ID, or a Pin Code), something the vast majority of the users do. On macOS, if biometrics are not available, the password cannot be stored in the keychain.
If the user opts to store the main password in this way, the device will require authentication when launching the application, through biometrics if configured, falling back to the Pin Code (on iOS) if no biometrics are available or the biometric-based authentication fails. If the user does not provide a valid biometric or Pin Code, the application falls back to requiring the user to type the main password, as if no password had been stored in the keychain. If the user opts for not storing the main password in the keychain, the application always asks for the main password when launching.
Either way, if authentication is not provided, the application wont proceed since it would not be possible to decrypt the stored content, or encrypt new content.
When the user changes the main password, the global key is unwrapped using a temporary key derived from the old password as described above, a new temporary key is derived from the new password, the global key is wrapped by the new temporary key, and stored on disk, replacing the old stored key.
When a document is created, a new random 256-bit key is generated specifically for that document. That key is wrapped by the global key, and stored in the file system. Each document's title and content is encrypted with its document specific key using the ChaCha20-Poly1305 algorithm. Before encryption, a random number of random bytes is added to the plain-text. This is used to intentionally increase the size of the data by an arbitrary amount, preventing an attacker from knowing the real size of the encrypted data. This is useful in situations where a message contains only a password, where knowing the exact size of the content can reduce the search space in a relevant amount. The padded data is added to the pain-text message itself, so it's subject to ChaCha20 encryption and Poly1305 authentication, preventing certain classes of attacks. When a document is deleted, its document-specific key is deleted from the file system as well. This means that even if an attacker is able to obtain any left-over information related to the document, they wont be able to decrypt it since the document-specific key is gone.
When the user changes the main password, the file specific keys are not affected, since they are wrapped by the global key. Even if the global key is re-wrapped by the temporary key derived from the new password so it can be stored safely in the file system, the global key itself never changes.
The information printed on the QR Codes consists of an encrypted data payload split by one or more segments (one per QR Code). Each QR Code contains that encrypted payload segment, and some non-encrypted information that guides PaperVault while scanning (like the total number of codes and a document identifier). More information about the data structures can be found in the data format page. The guiding data contains no sensitive information. For the purposes of this page, that information will be ignored and the focus will be on the data payload.
Before proceeding, it's important to note a document printed by PaperVault includes the document title printed in human-readable text in the page(s) header. The title is also included in the encrypted stream, so it can be scanned as part of the document. However, since the title is printed in human-readable form, it should not contain sensitive information.
The payload starts with one byte used for control flags. These flags are not part of the encrypted data stream, and are reserved for future information that needs to be present before decryption may happen. The rest of the payload is the encrypted data stream containing the document (content and title) plus another set of control flags (these ones encrypted themselves as part of the encrypted data stream, with information needed to decode the document after decryption takes place). The data format page contains all the details. For the purposes of this page, the important bit is how this information is encrypted.
When printing a document, the user may choose between using their main password (the same password used to encrypt the storage encryption key) or a different, document-specific password. Regardless of which password is used, similarly to what happens with documents stored on the device, a PBKDF2 function is used to derive an encryption key from the user-provided password, and a random salt. Also similarly to what was described before, 10 million rounds are used to derive the key. This key is used directly as the encryption key for the printed document's encrypted stream. Just like stored documents, a random number of random bytes is added to the plain-text stream before encryption. The stream is encrypted using the ChaCha20-Poly1305 algorithm as well, and prepended with the information needed to decrypt it (number of rounds and salt).
When the user scans a document, the payload is decrypted deriving the key from the user-provided password in the same way as during the encryption process. PaperVault will try to decrypt using the current user's main password. If that fails, the user will be prompted for the correct password for the scanned document.
PaperVault does not make any network calls. As stated before, when a document is printed, the data is encrypted and encoded in the QR Codes themselves, not in any cloud service. On macOS, PaperVault is sandboxed without network access. That said, there are situations when encrypted data may be transmitted across the network or to different devices as part of normal operation of your devices. In these situations, the data is always encrypted, be it in printed form (QR Codes) or data stored on device, except for the document title when printing.
These situations include backups (iCloud backups or backups to a Mac or PC on iOS, and any backup system used on macOS, like Time Machine and other third party backup products). You can find more about what is backed up below. Other situations include:
Many users configure their devices to regularly back up their data. On iOS, this includes backing up to iCloud or a computer (Mac or PC). On macOS, there are quite a few options, from Time Machine to locally attached or network volumes, to third party products that can use a panoplia of backup destinations, like multiple cloud services, SFTP servers, etc. Read this section to learn how information is backed up and how that affects security.
On iOS, if iCloud backups are turned on, PaperVault data can be excluded from backups by configuring the device appropriately using iOS Settings. As far as the author is aware, there is no way to do the same when backing up to a computer.
Here's what is backed up:
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
. This tells the operating system to protect the password with a device specific key. The password will be backed up as part of the device's keychain, but can only be restored to the same device. If the backup is restored to a different device, the user must type their main password again. This protects against an attacker who has access to a backup from restoring it to a different device, since, without the password, the restored PaperVault data will be useless. If you're a developer, here's a good summary of the different keychain accessibility values.Remember that, by default, iCloud backups are not protected by end-to-end encryption, meaning your backed up data can be obtained by third parties, including surrendered to authorities, in specific situations. Apple offers Advanced Data Protection in most jurisdictions. Advanced Data Protection enables end-to-end encryption, protecting your backups. Read more about Advanced Data Protection on Apple's website to understand how to turn it on and its implications in your devices usage, specifically recovery methods.