Skip to main content
The current implementation builds SQL queries by direct string concatenation, which is vulnerable to SQL injection. Do not use in production without replacing queries with parameterized statements.

Database schema

Vault uses a single SQLite table:
CREATE TABLE IF NOT EXISTS keys(
  label TEXT PRIMARY KEY,
  type  TEXT,
  data  TEXT
);
ColumnTypeDescription
labelTEXT PRIMARY KEYHuman-readable key name, e.g. "default-rsa"
typeTEXTKey algorithm identifier. See key types below.
dataTEXTKey material. PEM string for RSA; empty string for PQC stubs.

Key types

ValueDescription
"rsa"PEM-encoded RSA private key produced by Crypto::generate_rsa()
"dilithium"Planned post-quantum key (Dilithium). Currently stored as an empty string — pqc_generate() is a stub.

Constructor

Vault(const std::string& path)

Opens (or creates) the SQLite database file at the given path. The constructor calls sqlite3_open internally.
path
std::string
required
Filesystem path to the SQLite database file, e.g. "vault.db". The file is created if it does not exist.
Vault vault("vault.db");

Methods

void init()

Creates the keys table if it does not already exist. Must be called once before any store_key or get_key calls. Parameters: None Returns: void
Vault vault("vault.db");
vault.init();

void store_key(const std::string& label, const std::string& type, const std::string& data)

Inserts or replaces a key record. Uses INSERT OR REPLACE INTO keys VALUES(...) semantics — if a key with the same label already exists, it is overwritten.
label
std::string
required
Unique name for the key, e.g. "default-rsa" or "default-pq". Acts as the primary key.
type
std::string
required
Algorithm identifier. Use "rsa" for RSA keys or "dilithium" for post-quantum keys.
data
std::string
required
Key material as a string. For RSA keys, pass the PEM-encoded private key returned by Crypto::generate_rsa(). For PQC keys, pass an empty string (the current stub produces no key material).
Returns: void
Vault vault("vault.db");
vault.init();

std::string pem = Crypto::generate_rsa();
vault.store_key("default-rsa", "rsa", pem);

// Overwrite an existing entry
std::string pem2 = Crypto::generate_rsa();
vault.store_key("default-rsa", "rsa", pem2);

std::string get_key(const std::string& label)

Retrieves the data column for the key with the given label. Executes SELECT data FROM keys WHERE label=<label>.
label
std::string
required
The label used when the key was stored.
Returns: std::string — the stored key data (PEM string for RSA). Returns an empty string "" if no key with that label exists.
Vault vault("vault.db");
vault.init();

vault.store_key("default-rsa", "rsa", Crypto::generate_rsa());

std::string pem = vault.get_key("default-rsa");
// pem contains the PEM-encoded RSA private key

std::string missing = vault.get_key("no-such-key");
// missing == ""

Complete example

This mirrors the startup sequence in pkcs11-daemon/daemon.cpp:
#include "vault.h"
#include "crypto.h"
#include <iostream>

int main() {
    Vault vault("vault.db");
    vault.init();

    // Store RSA key
    std::string rsa = Crypto::generate_rsa();
    vault.store_key("default-rsa", "rsa", rsa);

    // Store PQC key (stub — empty string)
    std::string pq = Crypto::pqc_generate();
    vault.store_key("default-pq", "dilithium", pq);

    // Retrieve
    std::string retrieved = vault.get_key("default-rsa");
    std::cout << retrieved.substr(0, 27) << "\n";
    // Output: -----BEGIN PRIVATE KEY-----

    return 0;
}

Build docs developers (and LLMs) love