Skip to content

About

KeePass password database import/export library.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

 
 

Repository files navigation

libkeepass

Build Docs CodeQL codecov License: GPL v3 C++ Standard Platform

C++17 library for importing and exporting KeePass password databases.

This project is a fork of libkeepass by Christian Kindahl.

Documentation

The API documentation is available at https://dkruempe.github.io/libkeepass/.

Features

  • Formats: KDB (Legacy) and KDBX (KeePass2)
  • Unified API: One KeePass class with format auto-detection and in-memory stream support
  • Ciphers: AES, Twofish, ChaCha20
  • KDFs: AES-KDF, Argon2d, Argon2id
  • Keys: Password, Keyfile, Composite Keys
  • Platforms: Linux, macOS, Windows

Prerequisites

  • C++17 compatible compiler (GCC 10+, Clang 12+, MSVC 19.20+)
  • CMake >= 3.16
  • Conan package manager

Dependencies (installed automatically via Conan)

Build

# Install dependencies
conan install . --output-folder=build --build=missing

# Configure CMake (Release)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=build/Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release

# Build
cmake --build build --config Release

Running Unit Tests

cd build
ctest --output-on-failure

Generating the API Documentation

The public API is documented with Doxygen. To generate the HTML documentation locally:

# If Doxygen is installed, the 'doc' CMake target builds it
cmake --build build --target doc

Alternatively, run Doxygen directly:

doxygen Doxyfile        # output goes to docs/html

A hosted version of the documentation is auto-generated and published to GitHub Pages on every push to main.

Integration

Installing the library

After building (see Build), install the library and its CMake package to a prefix:

cmake --install build --prefix /usr/local

This installs the shared library, the public headers and a CMake package configuration, so consumers can use find_package(libkeepass).

Using it from CMake

cmake_minimum_required(VERSION 3.16)
project(my_app LANGUAGES CXX)

# Point CMake at the install prefix (only needed for non-standard prefixes)
list(APPEND CMAKE_PREFIX_PATH "/usr/local")

find_package(libkeepass REQUIRED)

add_executable(my_app main.cc)
target_link_libraries(my_app PRIVATE kruempelmann::libkeepass)

The imported target kruempelmann::libkeepass provides all required include paths and link dependencies (OpenSSL, zlib, pugixml, Argon2) transitively, so most consumers only need the find_package call.

Using it as a Git submodule

Alternatively, add this repository as a submodule and include it directly in your build tree. The target kruempelmann::libkeepass is available for both find_package and add_subdirectory style integration:

git submodule add https://github.com/dkruempe/libkeepass.git third_party/libkeepass
add_subdirectory(third_party/libkeepass/src)

add_executable(my_app main.cc)
target_link_libraries(my_app PRIVATE kruempelmann::libkeepass)

Note: add_subdirectory requires the same dependencies (OpenSSL, zlib, pugixml, Argon2) to be resolvable in your build tree, e.g. via Conan, as described under Prerequisites.

CMake components

The KDB and KDBX codecs are optional (LIBKEEPASS_COMPONENT_KDB, LIBKEEPASS_COMPONENT_KDBX). The installed package reports libkeepass_<component>_FOUND and provides kruempelmann::libkeepass::model/kdb/kdbx/capi interface targets:

find_package(libkeepass REQUIRED COMPONENTS kdbx)
target_link_libraries(my_app PRIVATE kruempelmann::libkeepass::kdbx)

Using it as a Conan package

The repository ships a Conan 2 recipe (conanfile.py) that builds and packages the library. To create the package from the current sources:

conan create . --build=missing

The version is read from CMakeLists.txt such that conan create always matches the current release. To build a specific variant pass -o libkeepass/*:shared=True for a shared library (static is the default).

Consumers declare the package in their conanfile.txt / conanfile.py:

[requires]
libkeepass/0.2.0

and use it from CMake as before:

find_package(libkeepass CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE kruempelmann::libkeepass)

Packaging

An in-tree vcpkg port is available under ports/libkeepass/, and an optional Homebrew formula is in Formula/libkeepass.rb:

vcpkg install libkeepass --overlay-ports=ports

CPack generates installable packages from the install rules. After building the project, run:

cmake --build build --target package

The generated packages are written to the build directory:

  • TGZ and ZIP archives on all platforms
  • DEB and RPM packages on Linux

To produce Linux packages for a specific target distribution, set the base install prefix accordingly:

cmake -B build -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
cmake --build build --target package

Note: The DEB/RPM dependency lists (libssl3, zlib1g, libpugixml1.12, libargon2-1 / openssl-libs, zlib, libpugixml, argon2-libs) are defaults and may need adjusting for your target distribution. Override them as needed, e.g. -DCPACK_DEBIAN_PACKAGE_DEPENDS="...".

Release assets are signed keylessly with Sigstore. Verify an artifact with:

cosign verify-blob \
  --certificate artifact.pem \
  --signature artifact.sig \
  --certificate-identity-regexp 'https://github.com/dkruempe/libkeepass/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  artifact

WebAssembly demo

wasm/ contains an Emscripten build of the C ABI and a client-side-only demo page. Decryption happens in the browser tab; no database bytes leave the machine. See wasm/README.md for the dependency/toolchain notes.

Command Line Interface

The kpx binary (in cli/) is a full command line tool built on top of the library and serves as a complete usage example:

kpx --help

# Print all entries as text (default), JSON or CSV
kpx -p password database.kdbx
kpx -p password -f json database.kdbx
kpx -p password -f csv --with-passwords database.kdbx

# Search and filter the output
kpx -p password --search alice database.kdbx
kpx -p password --search "^mail" --regex database.kdbx
kpx -p password --group Internet database.kdbx

# Generate a random password (default length 16, max 256)
kpx --generate
kpx --generate 32

# Create a database, change its credentials, and inspect its group tree
kpx -p password create database.kdbx
kpx -p password --new-password "$NEW_SECRET" passwd database.kdbx
kpx -p password groups database.kdbx

# Move an entry (or a group with --group) to another group
kpx -p password --search alice --to Archive move database.kdbx

# Merge another database (same master password/keyfile) into this one
kpx -p password --from old-backup.kdbx merge database.kdbx

# Edit the database in place
kpx -p password add --title "New" --user alice --pass secret --group Internet database.kdbx
kpx -p password update --search alice --notes "changed" database.kdbx
kpx -p password rm --title "Obsolete" database.kdbx

# Export to a new KeePass file (.kdb / .kdbx)
kpx -p password -e output.kdbx database.kdb

# Audit the password quality and reuse of all entries (or of one subtree)
kpx -p password --audit database.kdbx
kpx -p password --audit --group Internet database.kdbx
kpx -p password --audit -f json --with-passwords database.kdbx

# Show stored TOTP seeds, or generate the current codes
kpx -p password otp database.kdbx
kpx -p password --code otp database.kdbx

# Trim history to the newest N versions instead of clearing it
kpx -p password --all --keep 10 purge database.kdbx

# Keep the password out of argv and the environment
printf '%s\n' "$SECRET" | kpx --password-stdin database.kdbx
kpx --password-file /run/secrets/keepass database.kdbx

# Passwords can also come from an environment variable or an interactive prompt
KEEPASS_PASSWORD=secret kpx database.kdbx

The password is read from --password, --password-file <path> (or - for stdin), --password-stdin, KEEPASS_PASSWORD, or an interactive prompt (POSIX terminals and Windows consoles). --password and KEEPASS_PASSWORD are convenient but expose the secret through the process list or environment; use the file/stdin variants for scripts and services. Keyfiles are supported via --keyfile <path> and can also be passed as bytes through Key::FromBytes/Key::FromStream. Exit codes are stable per category (0 success, 1 command/usage error, 3 wrong password/key, 4 corrupt or unsupported database, 5 I/O or missing file); with --format json errors are printed as {"error":{"category":...,"message":...}}. See docs/cli-output.md for the output schemas and kpx --help for the full option and command reference.

Usage

Unified API (recommended)

The KeePass class is the single entry point for opening and saving databases. The input format is auto-detected; the output format is derived from the file extension and the database KDF/cipher, or can be forced explicitly:

#include "libkeepass/keepass.hh"

// Open with a password (and optionally a keyfile).
keepass::KeePass keeper("password", "/path/to/keyfile.key");
std::unique_ptr<keepass::Database> db = keeper.Open("database.kdbx");

// Manipulate the database...
auto root = db->root();
for (const auto& entry : root->Entries()) {
    std::cout << entry->path() << std::endl;
}

// Save back.
keeper.Save("output.kdbx", *db);

// Save encrypted with a different password.
keeper.SaveAs("output.kdbx", *db, "new_password");

// Force the output format.
keeper.SetFormat(keepass::KeePass::Format::kKdb);   // kKdb, kKdbx3, kKdbx4

Both Open and Save work with in-memory streams:

std::ostringstream out;
keeper.Save(out, *db);

std::istringstream in(out.str());
std::unique_ptr<keepass::Database> reopened = keeper.Open(in);

Create brand-new databases with generated cryptographic material:

auto db = keepass::KeePass::Create(
    "password", keepass::KeePass::Format::kKdbx4,
    keepass::Database::Cipher::kAes, keepass::Database::Kdf::kArgon2id);

Convenience API

Database, Group and Entry provide helpers for common operations:

// Database-level lookups (case-insensitive substring, or regex).
for (const auto& entry : db->FindEntries("github"))
    std::cout << entry->path() << std::endl;
auto group = db->FindGroup("Work");
auto entry = db->FindEntry("Home Banking");

// Build and modify the hierarchy.
auto new_entry = Database::NewEntry("A New Login");
Database::AddEntry(group, new_entry);
Database::MoveEntry(new_entry, other_group);
db->DeleteEntry(new_entry->uuid());

// Move groups, entries or a whole subtree into the recycle bin.
db->EnableRecycleBin(true);
db->TrashEntry(entry);
db->EmptyRecycleBin();

// Serialize the whole database to JSON or traverse it with a visitor.
std::string json = db->ToJson();
class CountingVisitor : public keepass::Visitor {
    void Visit(keepass::Group&) override { ++groups_; }
    void Visit(keepass::Entry&) override { ++entries_; }
    std::size_t groups_ = 0, entries_ = 0;
};
CountingVisitor visitor;
db->Visit(visitor);

C ABI / language bindings

libkeepass-c is a stable C surface for FFI consumers (capi/include/libkeepass-c.h). It exposes opaque handles, open/save, JSON/CSV export, entry lookup and simple editing:

#include <libkeepass-c.h>

kp_keepass* kp = kp_keepass_create("password", NULL);
kp_database* db = NULL;
if (kp_keepass_open(kp, "database.kdbx", &db) == KP_STATUS_OK) {
    char* json = NULL;
    kp_database_to_json(db, 0, &json);
    puts(json);
    kp_free_string(json);
}
kp_database_destroy(db);
kp_keepass_destroy(kp);

The wrapper is built by default; disable it with -DLIBKEEPASS_BUILD_C_API=OFF. Errors use the categories from the C++ API and are also available through kp_last_error().

Low-level format classes

The format-specific classes remain available for low-level access:

KDBX (KeePass2):

#include "libkeepass/kdbx.hh"
#include "libkeepass/key.hh"

keepass::Key key("password");
keepass::KdbxFile file;
std::unique_ptr<keepass::Database> db = file.Import("database.kdbx", key);
file.Export("output.kdbx", *db, key);

KDB (Legacy):

#include "libkeepass/kdb.hh"
#include "libkeepass/key.hh"

keepass::Key key("password");
std::unique_ptr<keepass::Database> db = keepass::KdbFile::Import("database.kdb", key);
keepass::KdbFile::Export("output.kdb", *db, key);

Database Class

The Database class provides access to:

  • root() - Root group of the database
  • cipher() / set_cipher() - Encryption algorithm
  • kdf() / set_kdf() - Key Derivation Function
  • compress() / set_compress() - XML compression

Groups and Entries

auto root = db->root();

// Add a new group
auto group = Database::NewGroup("My Group");
Database::AddGroup(root, group);

// Add a new entry
auto entry = Database::NewEntry("My Entry");
entry->set_username(keepass::protect<std::string>("user", true));
entry->set_password(keepass::protect<std::string>("secret", true));
entry->set_url(keepass::protect<std::string>("https://example.com", false));
Database::AddEntry(group, entry);

Parent links are maintained automatically, so group->path(), entry->path() and parent() are available throughout the tree.

Project Structure

libkeepass/
├── src/                    # Library source code
│   ├── include/libkeepass/ # Public headers
│   ├── keepass.cc          # Unified KeePass API
│   ├── kdb.cc              # KDB format implementation
│   ├── kdbx_import.cc      # KDBX format implementation
│   ├── kdbx_export.cc      # KDBX format implementation
│   ├── database.cc         # Database convenience API
│   ├── entry.cc            # Entry convenience API
│   ├── group.cc            # Group convenience API
│   ├── key.cc              # Key management
│   ├── visitor.cc          # Visitor pattern
│   ├── cipher.cc           # Encryption
│   └── ...
├── test/                   # Unit tests
├── cli/                    # kpx command line tool
├── cmake/                  # CMake configuration
└── .github/workflows/      # CI/CD

CI/CD

GitHub Actions automatically builds and tests on the following platforms:

  • Ubuntu (GCC)
  • macOS (Clang)
  • Windows (MSVC)

Each platform is tested in both Debug and Release configurations. Additionally, dedicated workflows enforce clang-format formatting and clang-tidy static analysis on every push and pull request, and run CodeQL (including the security-and-quality query suite) plus a nightly security scan on the C++ code base.

Security

libkeepass stores secret material (keys, entry passwords, protected strings) in wiped, best-effort locked memory:

  • secure_zero scrubs buffers through a volatile write so the compiler cannot elide the wipe.
  • secure_alloc/secure_free use mlock/VirtualLock (best effort) and always zero the allocation before freeing it.
  • SecureBuffer<N> is a move-only, automatically zeroized buffer used for keys and derived key material.
  • secure_string holds strings without SSO in wiped, locked memory and is used for all secret entry fields.
  • Transient transformed keys, HMAC keys, master keys and inner random stream keys are zeroized immediately after their last use in both import and export.

Wiping is deterministic, but locking is best effort: systems that restrict mlock/VirtualLock (or where it fails) allow pages to be swapped out.

For supported versions and how to report a vulnerability, please see SECURITY.md.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for build instructions, the code style guide, and the pull request process.

License

This project is based on libkeepass by Christian Kindahl.

Copyright (C) 2014 Christian Kindahl Copyright (C) 2024 Dominik Kruempelmann

Licensed under the GNU General Public License v3.0.

About

KeePass password database import/export library.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages