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 |
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.

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;
}
🔐 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:
-
Gateway Initialization: The gateway manages all cryptographic operations and configuration
-
Single Persona Creation: Create one digital identity with hardware-secured keys - no wait time
-
Self-Encryption: Encrypt data for secure storage - instant encryption/decryption
-
Digital Signing: Sign documents for integrity verification - immediate signature/verification
-
Local Operations: All operations work locally without requiring network communication
-
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
-
✅ 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. |