First Steps

This page will guide you through the process of setting up Keychain Core. Keychain Core is the library upon which all other components depend, and gives you the ability to develop your own Keychain-enabled applications using numerous APIs to suit your needs.

Jump to Linux and MacOS installation steps.

Jump to Windows installation steps.

If you are designing an application to instead interface with the Keychain Web Server, you can skip this tutorial and go to the Keychain Web Server Getting Started page.

Artifactory

The Keychain Core library builds are located on the Keychain Jfrog public binary repositories at https://keychain.jfrog.io/artifactory/.

All releases are in the subtree keychain-core-release-generic, with the core library for Linux and MacOS found in /keychain-cpp and Windows in /keychain-csharp.

Linux and MacOS

Download

First, download the tarball from the repository. We can do this from the command line (please use your own values for variables)

# Keychain Core version
VERSION={keychain-version}

# Operating System (linux, macos, ios, iossimulator)
OS=linux

# CPU/IS Architecture (armv7, armv8, x64)
ARCH=x64

# URL for the Keychain Core library (static)
KCURL = {artifactory-base}/keychain-cpp

# Download 'keychain-cpp-release-{keychain-version}-linux-x64.tar.gz'
curl -X GET "$KCURL/keychain-cpp-release-$VERSION-$OS-$ARCH.tar.gz"

Install

Next, extract the contents of the tarball, which will create a folder of the same name without the .tar.gz

# creates folder 'keychain-cpp-release-{keychain-version}-linux-x64/'
tar zxf keychain-cpp-release-$VERSION-$OS-$ARCH.tar.gz

Now go into the new folder, navigate to scripts/, and execute install.sh. If your environment has a variable KEYCHAIN_HOME, then Keychain will be installed to that location. The default is ~/.keychain.

cd keychain-cpp-release-$VERSION-$OS-$ARCH
cd scripts

# KEYCHAIN_HOME=/opt/keychain ./install.sh  <- install Keychain into '/opt/keychain'
./install.sh

Now you have Keychain installed in $KEYCHAIN_HOME (or ~/.keychain). The directory contains the following files and folders:

bin/        Keychain test app
config/     configuration file skeleton
data/       SQL statements for the Keychain DB
include/    the Keychain Core headers for development
lib/        the Keychain Core shared library
scripts/    Scripts to install the SO and binaries

Further Steps

At this point, Keychain Core has been installed and can be used. The next few sections are "quality of life" enhancements that make development smoother.

Library Bindings

The library lib/libkeychain.so is unknown to the dynamic linker at this point. This means that when building and running applications on Keychain Core, you would need to specify -L<path_to_keychain/lib> and LD_LIBRARY_PATH=<path_to_keychain/lib>, respectively.

You can simplify this by letting the dynamic linker know about libkeychain.so. This requires root/sudo permissions, and is done like so:

# Note: /usr/lib is one option, but /usr/local/lib or /lib also work
cp lib/libkeychain.so /usr/lib/
ldconfig

Includes

Include files are in a similar state as the library, in that the C preprocessor doesn’t know where they are by itself. One way around this is to build with -I<path_to_keychain/include>. Another is to set the environment variable(s) C_INCLUDE_PATH and/or CPLUS_INCLUDE_PATH.

However, a better way would be to place the include files in one of the preprocessor’s search paths, such as /usr/include.

cp -r include/keychain/keychain /usr/include/
cp -r include/tkcrypt/tkcrypt /usr/include/

Windows

For Windows, the Keychain Core shared object is a DLL and found in the C# artifact.

Download

Go to the Keychain artifactory and navigate to keychain-core-release-generic/keychain-csharp, and click the latest version. The file will be named like keychain-csharp-2.4.2-windows-x86.zip (for 2.4.2).

For v2.4, only x86 binaries are available

Install

Unzip the file into a directory of your choice. For example, C:\Keychain\2.4.2.

Usage

With the archive unzipped and placed in a known directory, it can now be referenced in a C# .NET project.

This is done by adding a shared library reference to the project to the KeychainCli.dll file. See the image below.

Example of adding KeychainCli to the KeychainChat accelerator

After this step, the Keychain Core library can be used in the project.

Please keep in mind that for v2.4 the project will need to be compiled as x86 (32-bit) for the DLL to be recognized as valid.

Your First Keychain Application

Now that Keychain Core is installed, let’s create your first secure application. This example demonstrates the core concepts: creating a digital identity (persona), encrypting data for secure storage, and cryptographic signing for data integrity.

  • Python

  • C++

  • C

#!/usr/bin/env python3
"""
First Keychain Application - Secure encryption and signing with one persona
"""

from keychain import Gateway, SecurityLevel, SerializedData

def main():
    # Initialize the gateway with default configuration
    settings = Gateway.init("~/.keychain/config/keychain.json")
    gateway = Gateway(settings)

    print("🔐 Creating secure persona...")

    # Create a persona (digital identity)
    my_persona = gateway.create_persona("MyName", "demo", SecurityLevel.MEDIUM)

    print("📧 Encrypting data...")

    # Encrypt data for secure storage (self-encryption)
    secret_data = "This is my confidential information!"
    data = SerializedData(secret_data)
    encrypted = my_persona.encrypt(data, [])  # Empty recipients = encrypt for self

    print(f"✅ Data encrypted successfully")
    print(f"📤 Encrypted data type: {encrypted.data_type()}")

    print("🔓 Decrypting data...")

    # Decrypt the data
    decrypted = my_persona.decrypt(encrypted)
    recovered_data = decrypted.utf8_string()

    print(f"📬 Recovered: '{recovered_data}'")

    print("✍️  Signing document...")

    # Sign a document for integrity verification
    document = "Important contract v1.0"
    doc_data = SerializedData(document)
    signed_doc = my_persona.sign(doc_data, True)

    print("🔍 Verifying signature...")

    # Verify the signature
    is_valid = gateway.verify(signed_doc)
    verified_content = signed_doc.utf8_string()

    print(f"✅ Signature valid: {is_valid}")
    print(f"📄 Document: '{verified_content}'")
    print("✅ Secure operations successful!")

    # Cleanup
    Gateway.close()

if __name__ == "__main__":
    main()
/**
 * First Keychain Application - Secure encryption and signing with one persona
 */

#include <iostream>
#include <vector>
#include "keychain/gateway/gateway.hpp"
#include "keychain/cache/persona.hpp"

namespace kc = keychain;

int main() {
    try {
        // Initialize the gateway with default configuration
        kc::settings settings;
        kc::code result = kc::gateway::init(settings, "~/.keychain/config/keychain.json");
        if (result != kc::code::success) {
            std::cerr << "Failed to initialize gateway" << std::endl;
            return 1;
        }

        kc::gateway gateway(settings);

        std::cout << "🔐 Creating secure persona..." << std::endl;

        // Create a persona (digital identity)
        auto my_persona = gateway.create_persona("MyName", "demo", kc::security_level::medium);

        std::cout << "📧 Encrypting data..." << std::endl;

        // Encrypt data for secure storage (self-encryption)
        std::string secret_data = "This is my confidential information!";
        kc::serialized_data data(secret_data);

        std::vector<kc::contact> recipients;  // Empty = encrypt for self
        auto encrypted = my_persona.encrypt(data, recipients);

        std::cout << "✅ Data encrypted successfully" << std::endl;
        std::cout << "📤 Encrypted data ready for storage" << std::endl;

        std::cout << "🔓 Decrypting data..." << std::endl;

        // Decrypt the data
        auto decrypted = my_persona.decrypt(encrypted);
        std::string recovered_data = decrypted.utf8_string();

        std::cout << "📬 Recovered: '" << recovered_data << "'" << std::endl;

        std::cout << "✍️  Signing document..." << std::endl;

        // Sign a document for integrity verification
        std::string document = "Important contract v1.0";
        kc::serialized_data doc_data(document);
        auto signed_doc = my_persona.sign(doc_data, true);

        std::cout << "🔍 Verifying signature..." << std::endl;

        // Verify the signature
        bool is_valid = gateway.verify(signed_doc);
        std::string verified_content = signed_doc.utf8_string();

        std::cout << "✅ Signature valid: " << (is_valid ? "true" : "false") << std::endl;
        std::cout << "📄 Document: '" << verified_content << "'" << std::endl;
        std::cout << "✅ Secure operations successful!" << std::endl;

        // Cleanup
        kc::gateway::close();

    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
/**
 * First Keychain Application - Secure encryption and signing with one persona
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "keychain/gateway/gateway.h"
#include "keychain/cache/persona.h"

int main() {
    kc_settings_t* settings = NULL;
    kc_gateway_t* gateway = NULL;
    kc_persona_t* my_persona = NULL;
    kc_serialized_data_t* data = NULL;
    kc_encrypted_data_t* encrypted = NULL;
    kc_serialized_data_t* decrypted = NULL;
    kc_serialized_data_t* doc_data = NULL;
    kc_verifiable_data_t* signed_doc = NULL;

    printf("🔐 Initializing Keychain...\n");

    // Initialize the gateway
    const char* config_path = "~/.keychain/config/keychain.json";
    if (kc_gateway_init(&settings, config_path, strlen(config_path)) != KC_SUCCESS) {
        fprintf(stderr, "Failed to initialize gateway settings\n");
        return 1;
    }

    if (kc_gateway_construct(&gateway, settings) != KC_SUCCESS) {
        fprintf(stderr, "Failed to construct gateway\n");
        return 1;
    }

    printf("🔐 Creating secure persona...\n");

    // Create persona
    if (kc_gateway_create_persona(gateway, &my_persona, "MyName", 6, "demo", 4,
                                 KC_SECURITY_LEVEL_MEDIUM, true) != KC_SUCCESS) {
        fprintf(stderr, "Failed to create persona\n");
        goto cleanup;
    }

    printf("📧 Encrypting data...\n");

    // Create serialized data from secret
    const char* secret_data = "This is my confidential information!";
    if (kc_serialized_data_construct_from_utf8(&data, secret_data, strlen(secret_data)) != KC_SUCCESS) {
        fprintf(stderr, "Failed to create serialized data\n");
        goto cleanup;
    }

    // Encrypt for self (no recipients)
    if (kc_gateway_encrypt(gateway, &encrypted, my_persona, data, NULL, 0) != KC_SUCCESS) {
        fprintf(stderr, "Failed to encrypt data\n");
        goto cleanup;
    }

    printf("✅ Data encrypted successfully\n");
    printf("🔓 Decrypting data...\n");

    // Decrypt the data
    if (kc_gateway_decrypt(gateway, &decrypted, my_persona, encrypted) != KC_SUCCESS) {
        fprintf(stderr, "Failed to decrypt data\n");
        goto cleanup;
    }

    // Extract the decrypted data
    char* recovered_data = kc_serialized_data_utf8_string(decrypted);
    printf("📬 Recovered: '%s'\n", recovered_data);

    printf("✍️  Signing document...\n");

    // Create document data
    const char* document = "Important contract v1.0";
    if (kc_serialized_data_construct_from_utf8(&doc_data, document, strlen(document)) != KC_SUCCESS) {
        fprintf(stderr, "Failed to create document data\n");
        free(recovered_data);
        goto cleanup;
    }

    // Sign the document
    if (kc_gateway_sign(gateway, &signed_doc, my_persona, doc_data, true, NULL, 0, NULL, 0) != KC_SUCCESS) {
        fprintf(stderr, "Failed to sign document\n");
        free(recovered_data);
        goto cleanup;
    }

    printf("🔍 Verifying signature...\n");

    // Verify the signature
    bool is_valid = (kc_gateway_verify(gateway, signed_doc) == KC_SUCCESS);
    char* verified_content = kc_verifiable_data_utf8_string(signed_doc);

    printf("✅ Signature valid: %s\n", is_valid ? "true" : "false");
    printf("📄 Document: '%s'\n", verified_content);
    printf("✅ Secure operations successful!\n");

    // Free strings
    free(recovered_data);
    free(verified_content);

cleanup:
    // Cleanup resources
    if (signed_doc) kc_verifiable_data_destruct(&signed_doc);
    if (doc_data) kc_serialized_data_destruct(&doc_data);
    if (decrypted) kc_serialized_data_destruct(&decrypted);
    if (encrypted) kc_encrypted_data_destruct(&encrypted);
    if (data) kc_serialized_data_destruct(&data);
    if (my_persona) kc_persona_destruct(&my_persona);
    if (gateway) kc_gateway_destruct(&gateway);
    if (settings) kc_settings_destruct(&settings);

    kc_gateway_close();

    return 0;
}
Expected Output
🔐 Creating secure persona...
📧 Encrypting data...
✅ Data encrypted successfully
📤 Encrypted data type: ENCRYPTED_DATA
🔓 Decrypting data...
📬 Recovered: 'This is my confidential information!'
✍️  Signing document...
🔍 Verifying signature...
✅ Signature valid: true
📄 Document: 'Important contract v1.0'
✅ Secure operations successful!

What Just Happened?

This example demonstrates the core Keychain concepts with immediate results:

  1. Gateway Initialization: The gateway manages all cryptographic operations and configuration

  2. Single Persona Creation: Create one digital identity with hardware-secured keys - no wait time

  3. Self-Encryption: Encrypt data for secure storage - instant encryption/decryption

  4. Digital Signing: Sign documents for integrity verification - immediate signature/verification

  5. Local Operations: All operations work locally without requiring network communication

Key Security Features
  • Hardware-Secured Keys: Private keys are generated and stored in secure hardware

  • Instant Results: Self-encryption and signing work immediately without PKI delays

  • Data Integrity: Cryptographic proof that data hasn’t been tampered with

  • Secure Storage: Encrypted data can be safely stored or transmitted

Perfect for Getting Started
  • No network dependencies - everything works offline

  • No waiting - immediate cryptographic operations

  • Positive experience - successful results every time

  • Real security - hardware-backed cryptographic protection

Next Steps - Solution Accelerators

We recommend that you get familiar with the Keychain capabilities by downloading, building, and trying one or more of our solution accelerators.

These accelerators illustrate simple use cases and highlight usage patterns of Keychain Core in multiple programming languages and environments (primarily Java and Python on Linux, Android Java, and C#.NET on Windows).

These sample projects are provided as-is, solely for informational/educational purposes and do not represent production-level code.