A small C++17 library for password-protected files, with three operations:
create, read, and update.
Vault uses AES-256-GCM authenticated encryption and scrypt password derivation. OpenSSL 3.5 or newer is the only external dependency. The test executable uses a small local harness.
Requirements: CMake 3.24+, a C++17 compiler, and OpenSSL 3.5+ development files. OpenSSL 3.5 is the LTS baseline; use a current patched release of a supported series. On macOS with Homebrew:
brew install cmake openssl@3
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \
-DOPENSSL_ROOT_DIR="$(brew --prefix openssl@3)"
cmake --build build --parallel
ctest --test-dir build --output-on-failureOn Linux, install a supported OpenSSL development package (or build a supported
release) and use the same CMake commands. Set OPENSSL_ROOT_DIR when OpenSSL is
outside standard search paths. On Windows, use Visual Studio 2022 and vcpkg's
openssl:x64-windows, passing its CMake toolchain file when configuring; build
with --config Release and test with -C Release.
Use -DBUILD_TESTING=OFF for library-only builds, -DBUILD_SHARED_LIBS=ON for a
shared library, or -DVAULT_BUILD_EXAMPLES=ON to build vault_example.
The example accepts an output path and overwrites that file.
GCC/Clang on Unix also support -DVAULT_ENABLE_SANITIZERS=ON in a separate Debug build.
#include <vault.h>
int main() {
vault::userdata_t initial{'h', 'i'};
// Example only: obtain a real password securely rather than hardcoding it.
auto token = vault::create("example.vault", "example password", initial);
vault::update("example.vault", token, {'h', 'e', 'l', 'l', 'o'});
auto data = vault::read("example.vault", token);
vault::wipe(token);
vault::wipe(data);
auto reopened = vault::read("example.vault", "example password");
vault::wipe(reopened);
}read(path, password, &token) can also return a reusable token. The optional
output token is unchanged if the read fails. All failures throw
std::runtime_error, except standard allocation failures. Exception messages are
for diagnostics, not a stable machine-readable API.
- Reads verify the complete GCM tag before releasing plaintext. The header is authenticated too. Wrong credentials and modified ciphertext are rejected.
- Each create uses a new random 16-byte salt; each write uses a fresh random 12-byte nonce. The authentication tag is 16 bytes.
- scrypt uses fixed
N=131072, r=8, p=1parameters (about 128 MiB working memory), with a 256 MiB OpenSSL memory ceiling. Files cannot request arbitrary KDF work. - Tokens contain the raw 32-byte key and are bearer secrets. Anyone holding one can read and update that vault. They remain valid across updates; recreating the file invalidates old tokens. Copies of the same vault share token access.
wipe()cleanses the current bytes of a vector. It cannot erase copies, previously reallocated storage, caller-owned password strings, or OS snapshots. Internal keys and unsuccessful decryption buffers are cleansed automatically.- Passwords must contain 1–1,048,576 bytes; embedded NUL bytes are supported. Payloads may be empty and are limited to 64 MiB. Operations buffer files in memory.
- Writes use exclusive temporary files in the destination directory, flush file contents, and replace the destination. Failures before replacement preserve the original. POSIX files have owner-only permissions; Windows files inherit directory ACLs. Existing ownership, permissions, hard links, and extended attributes are not preserved. A destination symlink is replaced rather than followed on POSIX.
- Paths are UTF-8. Parent directories must exist and be trusted. Coordinate writers externally: there is no locking, compare-and-swap, rollback protection, or promise of persistence across power loss (the parent directory is not explicitly synced). Atomic replacement depends on the filesystem's rename/replacement guarantees.
- Password strength still matters. This library does not provide memory locking, secure deletion of old files, or a separately audited cryptographic implementation.
See the format specification for byte layouts.
cmake --install build --prefix /your/install/prefixConsumers set CMAKE_PREFIX_PATH to that prefix and use:
find_package(vault 1 CONFIG REQUIRED)
target_link_libraries(your_application PRIVATE vault::vault)MIT; see LICENSE.