Inroduction

What is SARE?

SARE (Safe At Rest Encryption) is a hybrid post-quantum encryption system designed to protect data against both classical and quantum attacks.

Unlike traditional encryption tools that rely on a single algorithm (e.g., RSA or AES), SARE combines classical algorithms like X25519 and Ed25519 with post-quantum algorithms like Kyber768, using a hybrid scheme. Even if one algorithm is broken in the future, your data remains secure.

Why SARE Matters

Quantum computers threaten the foundations of classical cryptography. Algorithms like RSA and ECC will be breakable once sufficiently powerful quantum machines exist.

Post-quantum algorithms are young and may still have vulnerabilities. SARE adopts a belt-and-suspenders approach: both classical and post-quantum schemes are used in parallel, giving robust protection today and forward-security tomorrow.

Key Features

  • Hybrid Key Encapsulation (KEM): Diffie–Hellman + PQ KEM to derive shared secrets.
  • Hybrid Signatures: Files are signed with both elliptic curves and PQ schemes; both signatures must validate.
  • File-Level Encryption: Files include headers, metadata, ciphertext, and optional signatures.
  • Master Seed: Single 128-byte seed derives all private keys.
  • Validation Certificates: Prove that your public keys are valid.
  • Revocation Certificates: Revoke compromised or obsolete keys.
  • Modular & Extensible: Swap or add encryption, signing, or KDF algorithms without rewriting core logic.
  • High-Level API via sare-lib: Makes it easy to integrate SARE into Rust applications.
  • CLI (sare-cli): Command-line interface for encryption, decryption, signing, and key management.
  • Security-Focused: Uses well-vetted, audited algorithms.

Project Layout

The SARE repository has three main components:

sare-core  - low-level cryptography primitives
sare-lib   - high-level library for file encryption and handling
sare-cli   - command-line interface for everyday use
  • sare-core is low-level and intended to be used through sare-lib. Developers should exercise caution if working directly with it.
  • sare-lib provides the main library API and handles file formatting, encryption, and key management.
  • sare-cli provides CLI commands for everyday tasks: encrypt, decrypt, sign, manage keys and recipients.

Installation and Usage

SARE can be used as a CLI tool or integrated into your Rust projects via sare-lib.

To get started and install / use SARE please read the Getting Started Page

Who is SARE For?

  • End users: Encrypt and sign files with long-term security.
  • Developers: Integrate hybrid PQ crypto into Rust applications.
  • Researchers: Experiment with hybrid cryptography in real-world settings.

Roadmap

  • Parallelized encryption/decryption for large files.
  • Additional post-quantum algorithms and signature schemes.
  • Key revocation workflows in the CLI.
  • Keyserver implementations for sharing keys.
  • Security audits and performance benchmarks.

License

  • Code: MIT + Apache 2.0
  • Books, guides, and documentation: CC BY 4.0

Getting Started with SARE

This section will help you quickly install SARE, learn the basics of the CLI, and explore examples using the sare-lib library.

Installation

Learn how to install sare-cli and sare-lib in your environment.

Go to Installation

Quickstart with CLI

See how to encrypt, decrypt, sign, and manage keys using the command-line interface.

Go to Quickstart with CLI

Sare Lib Examples

Explore examples demonstrating file encryption, decryption, and signing with sare-lib.

Go to Sare Lib Examples

Installation

Installing SARE CLI from Source

You can build SARE CLI directly from source. This is useful if you want the latest development version or need to tweak the code:

git clone https://github.com/SareProject/sare
cd sare
cargo build --release

The resulting binary will be located at:

target/release/sare-cli

You can then move it to a directory in your PATH for easier access:

mv target/release/sare-cli /usr/local/bin/sare-cli

Installation Using Cargo

For a simpler installation, you can install the latest released version directly from crates.io:

cargo install sare-cli

After installation, the sare-cli command will be available globally in your terminal.


Using SARE Lib in a Rust Project

To use SARE as a library in your Rust projects, add it to your dependencies in Cargo.toml:

[dependencies]
sare-lib = "0.1"    

Using Cargo to Add the Dependency

Alternatively, you can add sare-lib directly using Cargo:

cargo add sare-lib

This will automatically update your Cargo.toml and fetch the library from crates.io, making it ready for use in your project.

Quick Start with SARE CLI

SARE CLI is a command-line tool to manage keys, encrypt/decrypt files, and sign/verify files using hybrid post-quantum + classical cryptography.

Note: The CLI is fully functional, but some options (KDF customization, revocation broadcast) are not yet implemented. Defaults are used for now.


1. Generate a Master Key

sare-cli masterkey generate

This generates a new master key and creates:

  • Validation Certificate: Confirms your public keys are valid for a specified period.
  • Revocation Certificate: Can be published if your key is compromised.

Optional flags such as --hybrid-kem-algorithm or --hybrid-sign-algorithm are present in the CLI but not fully functional yet.

List available master keys:

sare-cli masterkey list

Remove a master key:

sare-cli masterkey remove <masterkey_id>

Export info about a master key:

sare-cli masterkey export <masterkey_id>

2. Add or Manage Recipients

Add a recipient (so you can encrypt files for them):

sare-cli recipient add <path-to-public-key.pem>

Remove a recipient:

sare-cli recipient remove <recipient_id>

List all recipients:

sare-cli recipient list

3. Encrypt and Decrypt Files

Asymmetric Encryption

Encrypt a file for a recipient:

sare-cli encrypt asymmetric <input_file> <output_file> --recipient <recipient_id>

Decrypt a file:

sare-cli decrypt <input_file> <output_file> --masterkey-id <masterkey_id>

Note: Currently, KDF and algorithm options are fixed and cannot be modified.

Symmetric Encryption

Encrypt a file symmetrically:

sare-cli encrypt symmetric <input_file> <output_file>

Decrypt:

sare-cli decrypt <input_file> <output_file>

4. Sign and Verify Files

Generate a signature for a file:

sare-cli signature generate <input_file> <sign_file> --masterkey-id <masterkey_id>

Verify a signature:

sare-cli signature verify <sign_file> <input_file>

5. Revocation Certificates

Generate a new revocation certificate (replaces old):

sare-cli revocation new --reason compromised --masterkey-id <masterkey_id>

List revocation certificates:

sare-cli revocation list

Note: revocation broadcast is not implemented yet because keyserver support is pending.

Example Usage of SARE Lib

Encrypting and Decrypting Files

SARE Lib allows you to encrypt and decrypt files using either symmetric (passphrase-based) or asymmetric (public/private key-based) methods. Below are examples for both approaches.


Symmetric Encryption

Use symmetric encryption when you want to protect a file using just a passphrase. This is fast and simple for personal use or sharing with a small group.

#![allow(unused)]
fn main() {
use sare_lib::{encryption::Encryptor, keys::{EncryptionAlgorithm, RECOMMENDED_PKDF_PARAMS}};
use secrecy::SecretVec;
use std::fs::File;

let input_file = File::open("message.txt")?;
let mut output_file = File::create("message.enc")?;
let passphrase = SecretVec::new(b"supersecret".to_vec());

// Generate key derivation function (KDF) using recommended parameters
let pkdf = Encryptor::get_pkdf(&passphrase, RECOMMENDED_PKDF_PARAMS, 1);

// Encrypt the file symmetrically using XChaCha20-Poly1305 AEAD
Encryptor::encrypt_with_passphrase(&mut input_file, &mut output_file, pkdf, EncryptionAlgorithm::XCHACHA20POLY1305)?;
}

Symmetric Decryption

To access your encrypted data, provide the same passphrase used during encryption.

#![allow(unused)]
fn main() {
use sare_lib::encryption::Decryptor;
use secrecy::SecretVec;
use std::fs::File;

let mut input_file = File::open("message.enc")?;
let mut output_file = File::create("message_decrypted.txt")?;
let passphrase = SecretVec::new(b"supersecret".to_vec());

Decryptor::decrypt_with_passphrase(passphrase, &mut input_file, &mut output_file)?;
}

Asymmetric Encryption

For secure sharing with others, use asymmetric encryption. You encrypt with the recipient’s public key, and only they can decrypt with their private key.

#![allow(unused)]
fn main() {
use sare_lib::{encryption::Encryptor, keys::{MasterKey, SharedPublicKey, EncryptionAlgorithm}};
use std::fs::File;

let input_file = File::open("document.txt")?;
let mut output_file = File::create("document.enc")?;

// Load master key and recipient public key
let master_key = MasterKey::load("MASTER_KEY.pem")?;
let recipient_key = SharedPublicKey::from_pem(std::fs::read_to_string("recipient.pem")?)?;

let encryptor = Encryptor::new(master_key);
encryptor.encrypt_with_recipient(&mut input_file, &mut output_file, &recipient_key, EncryptionAlgorithm::XCHACHA20POLY1305)?;
}

Asymmetric Decryption

The recipient can decrypt the file using their master key. SARE Lib also allows you to detect and verify any attached signatures automatically.

#![allow(unused)]
fn main() {
use sare_lib::encryption::Decryptor;
use std::fs::File;

// Load your master key
let master_key = MasterKey::load("MASTER_KEY.pem")?;
let decryptor = Decryptor::new(master_key);

let mut input_file = File::open("document.enc")?;
let mut output_file = File::create("document_decrypted.txt")?;

// Decrypt the file
let signature = decryptor.decrypt_with_recipient(&mut input_file, &mut output_file)?;

if let Some(sig) = signature {
    println!("Signature attached: {:?}", sig.fullchain_fingerprint);
}
}

Signing and Verifying

SARE allows you to create detached signatures, ensuring that your files can be verified without modifying the original content.

Detached Signature

#![allow(unused)]
fn main() {
use sare_lib::signing::Signing;
use std::fs;

let master_key = MasterKey::load("MASTER_KEY.pem")?;
let signer = Signing::new(master_key);

let message = fs::read("report.txt")?;
let signature = signer.sign_detached(&message);
fs::write("report.sig", signature.encode_with_magic_byte())?;
}

Verifying a Detached Signature

Verification ensures the integrity and authenticity of a file by comparing it with the signature.

#![allow(unused)]
fn main() {
use sare_lib::signing::Signing;
use sare_lib::format::signature::SignatureHeaderFormat;
use std::fs;

let signed_file = fs::read("report.sig")?;
let original_file = fs::read("report.txt")?;

let signature_header = SignatureHeaderFormat::decode_with_magic_byte(&signed_file)?;
let is_valid = Signing::verify_detached(&signature_header, &original_file)?;

println!("Signature valid: {}", is_valid);
}

Master Key Management

Master keys are central to SARE's security. They allow you to manage encryption, signing, and validation certificates.

Generate a Master Key

#![allow(unused)]
fn main() {
use sare_lib::keys::{MasterKey, HybridKEMAlgorithm, HybridSignAlgorithm};

let master_key = MasterKey::generate(
    HybridKEMAlgorithm::default(),
    HybridSignAlgorithm::default()
);

// Export the master key (optionally encrypted with a passphrase)
master_key.export(Some("supersecret".as_bytes().to_vec().into()), &mut std::fs::File::create("MASTER_KEY.pem")?)?;

// Export public key
master_key.export_public(&mut std::fs::File::create("PUB_KEY.pem")?)?;
}

Inspect a Master Key

You can inspect master keys to verify fingerprints or recover mnemonic seeds.

#![allow(unused)]
fn main() {
let master_key = MasterKey::load("MASTER_KEY.pem")?;
println!("Master Key Fingerprint: {:?}", master_key.get_fullchain_public_fingerprint());
println!("Mnemonic Seed: {}", master_key.to_mnemonic().expose_secret());
}

Revoke a Master Key

If a key is compromised or no longer needed, create a revocation certificate to signal that it should not be used.

#![allow(unused)]
fn main() {
use sare_lib::{certificate::Certificate, format::certificate::Issuer, format::certificate::RevocationReason};

let master_key = MasterKey::load("MASTER_KEY.pem")?;
let issuer = Issuer::new("Your Name", "your@email.com");

let revocation_cert = Certificate::new_revocation(master_key, 1682611200, issuer, RevocationReason::NoReasonSpecified);
revocation_cert.export(std::fs::File::create("REVOC_KEY.asc")?)?;
}

Recipient Management

Recipients represent the people you share encrypted files with. SARE makes it easy to add, export, and verify recipient keys.

#![allow(unused)]
fn main() {
use sare_lib::keys::SharedPublicKey;

// Add a recipient
let recipient_key = SharedPublicKey::from_pem(std::fs::read_to_string("recipient.pem")?)?;
recipient_key.export(std::fs::File::create("RECIPIENT.pem")?)?;

// Load and list recipients
let recipient_key = SharedPublicKey::from_pem(std::fs::read_to_string("RECIPIENT.pem")?)?;
println!("Recipient fingerprint: {:?}", recipient_key.fullchain_public_key.calculate_fingerprint());
}

Technical Reference

This section provides a deep dive into the internal structure and cryptographic foundations of SARE.
It is intended for developers and security researchers who want to understand how SARE works under the hood, integrate it into their own applications, or audit its design.

SARE is split into three layers:

  • sare-core: Low-level cryptographic operations and file format handling.
  • sare-lib: High-level library built on top of sare-core to make integration easy.
  • sare-cli: A command-line interface that demonstrates and exposes SARE’s features.

Contents

  • SARE File Format
    Describes how encrypted files are structured, including metadata, nonces, checksums, and signatures.

  • Cryptographic Primitives
    The algorithms and operations that form the foundation of SARE, including hybrid KEM, hybrid signatures, and KDFs.

  • Certificates
    Validation and revocation certificates, their structure, and their role in the trust model.

  • SareDB
    A CLI-only JSON database for managing keys and recipients. Not part of the library but used in sare-cli.

Design Notes

  • Self-describing encryption: Metadata contains everything needed to decrypt.
  • Hybrid classical + post-quantum: Ensures security both today and in a future with large-scale quantum computers.
  • Clear separation of layers: sare-core provides primitives, sare-lib simplifies usage, and sare-cli offers practical workflows.

For detailed information, follow the links in each section.

File Formatting in SARE

SARE defines its own structured formats for both encrypted files and signature files, providing consistency, versioning, and support for cryptographic metadata. This ensures that files can be properly decoded, verified, and decrypted across different SARE implementations.

Encrypted Files Format

Encrypted files in SARE are not just raw ciphertext—they include a structured header containing all metadata necessary for decryption and verification.

Structure

  1. Magic bytes:
    A predefined sequence to identify the file as a SARE-encrypted message.

  2. Version:
    Each file includes a version number to allow backward and forward compatibility. The current SARE version is embedded in the header.

  3. Encryption metadata:
    This metadata is part of the file header and includes:

    • The symmetric encryption algorithm used (e.g., XChaCha20-Poly1305 for files).

    • Nonces for stream encryption.

    • Optional PKDF metadata if password-based encryption is used.

    • Optional KEM metadata if asymmetric encryption is used, describing the key encapsulation and shared secrets.

Encoding and Decoding

  • The header is encoded in binary.

  • The metadata is BSON-serialized, allowing easy extension while keeping the structure machine-readable.

  • During decryption, SARE reads the header, extracts metadata, derives the encryption key (via PKDF or HybridKEM + HKDF), and then decrypts the file content.

Note: Encrypted files are strictly binary-encoded. PEM/ASCII-armoring is not used for encrypted files.

Signature Files Format

Signature files in SARE store cryptographic signatures independently of encrypted content. They follow a structured, self-contained format.

Structure

  1. Magic bytes:
    Each signature file starts with SARESIGN to identify it as a SARE signature.

  2. Versioning:
    A u32 version number is included to support backward and forward compatibility.

  3. Signature metadata:
    Metadata includes:

    • EC and post-quantum (PQ) algorithms used.

    • Optional cryptographic metadata, such as public keys and algorithm parameters.

  4. Signature content:

    • Public keys (EC and PQ)

    • The message itself (optional; None for detached signatures)

    • EC and PQ signature values

    • Full-chain fingerprint for verification

Encoding and Decoding

  • Signature files can be encoded in binary (via BSON) or as PEM-encoded files:

    • Binary encoding is standard.

    • PEM encoding provides ASCII-armored files, though SARE CLI currently does not implement the armor option.

  • Methods:

    • encode_with_magic_byte() / decode_with_magic_byte() handle the header and magic bytes.

    • encode_bson() / decode_bson() handle metadata serialization.

    • encode_pem() / decode_pem() allow ASCII-armored serialization.

Notes

  • Certificates in SARE use the same BSON-encoded signature format but are documented separately.

  • Detached and attached signatures are supported; the presence of message indicates an attached signature.


This design ensures that both encrypted files and signature files are self-describing, versioned, and extensible while remaining secure and compatible across SARE implementations.

Cryptographic Primitives

Cryptographic primitives are the building blocks of secure systems.
They include encryption algorithms, signature schemes, key exchange methods, and key derivation functions.
SARE combines classical elliptic-curve cryptography with post-quantum algorithms to provide long-term security.


Symmetric Cryptography

Symmetric algorithms are used for encrypting file contents and wrapping keys.
They are efficient and secure, even in the post-quantum era.

  • XChaCha20-Poly1305 — AEAD algorithm for streaming encryption with confidentiality and integrity.
  • AES-256-GCM — AEAD alternative based on AES.
  • AES-256 Key Wrap (AES-KW) — Used to wrap (encrypt) symmetric keys securely.

Each encrypted file includes a unique nonce in its metadata to prevent key/nonce reuse attacks.


Asymmetric Cryptography

Asymmetric primitives are used for exchanging keys, verifying identities, and creating digital signatures.

  • Classical algorithms:

    • Ed25519 (signatures)
    • X25519 (key exchange)
  • Post-quantum algorithms:

    • Dilithium3 (signatures)
    • Kyber (key encapsulation mechanism)

Hybrid KEM

SARE’s Hybrid KEM combines:

  • A classical Diffie-Hellman exchange (X25519)
  • A post-quantum KEM (Kyber)

This produces two shared secrets.
SARE then uses HKDF to derive a final symmetric key by hashing the concatenation of both secrets.
This ensures security against both classical and quantum adversaries.
Read more →


Hybrid Signatures

When signing data, SARE generates two signatures:

  • One classical (Ed25519)
  • One post-quantum (Dilithium3)

Both signatures must verify successfully.
This ensures trust even if one algorithm is broken in the future.
Read more →


Key Derivation Functions (KDFs)

Key derivation is central to SARE:

  • HKDF: Derives symmetric keys from shared secrets in Hybrid KEM.
  • PKDF: Derives keys from user passphrases when encrypting with a password.

Each derived key is tied to a salt and algorithm identifier, preventing reuse across contexts.
Read more →


Randomness & Nonces

Every encryption uses secure randomness:

  • Nonces ensure ciphertext uniqueness.
  • Salts in KDFs prevent rainbow-table attacks.

The randomness source is the system’s cryptographically secure RNG.


Summary

Primitive TypeAlgorithm(s) UsedPurpose
SymmetricXChaCha20-Poly1305, AESFile encryption, AEAD
Key WrappingAES-KWEncrypting symmetric keys
Asymmetric (class.)X25519, Ed25519DH exchange, digital signatures
Asymmetric (PQ)Kyber, Dilithium3PQ KEM, PQ signatures
KDFsHKDF, PKDFDeriving keys from secrets or passphrases

These primitives form the secure foundation for SARE’s encryption, signatures, and certificate model.

Hybrid KEM (Key Encapsulation Mechanism)

SARE uses a Hybrid Key Encapsulation Mechanism (KEM) to securely derive encryption keys for asymmetric file encryption. The hybrid approach combines a classical Diffie-Hellman key exchange with a post-quantum KEM, ensuring robust security even against future quantum attacks.

The hybrid KEM generates two independent shared secrets that are later combined and processed to produce a single symmetric encryption key for AEAD encryption.

Supported Algorithms

Currently, SARE supports the following hybrid KEM algorithms:

  • Classical DH: X25519

  • Post-Quantum KEM: Kyber768

Each hybrid KEM consists of a classical DH component and a post-quantum KEM component. Additional algorithms can be added as needed.

Shared Secret Generation

  1. Classical DH Shared Secret

    • Generated using the sender’s DH keypair and the recipient’s DH public key.

    • In sare-core: DiffieHellman::calculate_shared_key() → ss1.

  2. Post-Quantum KEM Shared Secret

    • Generated using the sender’s KEM keypair and the recipient’s KEM public key.

    • In sare-core: Decapsulation::decapsulate() → ss2.

These two secrets are independent and form the basis of the final symmetric key derivation.

Encryption Key Derivation with HKDF

SARE combines the two shared secrets as follows in sare-lib:

combined_ss = ss1 || ss2

Then it derives the final encryption key using HKDF-SHA256:

encryption_key = HKDF(combined_ss, salt, info)
  • combined_ss – Concatenation of the two shared secrets.

  • salt – Randomly generated per encryption session.

  • info – Optional contextual info (can be None).

  • encryption_key – Final key used for AEAD encryption.


This design ensures that the compromise of one component does not expose the encryption key, providing post-quantum resilience for encrypted files.

Hybrid Signatures

Hybrid Signatures in SARE combine a classical digital signature with a post-quantum signature to ensure long-term integrity and non-repudiation of files.

The rationale for using a hybrid approach is to future-proof signatures against quantum attacks while maintaining compatibility with current cryptographic standards. By combining classical and post-quantum signatures, SARE ensures that a file remains verifiable even if one algorithm is later broken.

How Hybrid Signatures Work

When a file is signed in SARE:

  1. Classical Signature Generation

    • Typically uses Ed25519.

    • Signs the SHA3-256 checksum of the file or message.

  2. Post-Quantum Signature Generation

    • Uses a PQ signature algorithm (e.g., Dilithium or Falcon, depending on configuration).

    • Also signs the same file checksum.

Both signatures are generated independently but stored together.

Verification Rule:

  • A file is only considered authentic if both signatures verify correctly.

  • Failure of either signature invalidates the file’s integrity.

Signature Formatting

SARE stores signatures in a structured format included in the file header:

SignatureFormat {
    ec_signature: Vec<u8>,  // e.g., Ed25519
    pq_signature: Vec<u8>,         // e.g., Dilithium
    fullchain_fingerprint: [u8; 32], // Identifier for the keychain used
    signature_metadata: Option<...>,  // Additional metadata such as version, key ID
}
  • ec_signature – The bytes of the classical signature.

  • pq_signature – The bytes of the post-quantum signature.

  • fullchain_fingerprint – Fingerprint of the signer’s keychain to identify which key generated the signature.

  • signature_metadata – Optional metadata that may include algorithm versioning or key identifiers.

End Result:

  • When a file is encrypted or signed, the hybrid signature is attached to the file header.

  • Tools like the CLI will verify both signatures and report validity.

Master Keys

A Master Key in SARE is the root secret that deterministically derives all cryptographic keys (encryption, signing, hybrid, etc.). Its security relies on the master seed, which must be stored securely.

Master Seed

  • The master seed is a high-entropy secret, stored as a SecretVec<u8>.

  • Generated via a cryptographically secure RNG.

  • Used to deterministically derive all hybrid KEM/Sign keypairs.

Master Key Storage Formats

Secret Key Format (SecretKeyFormat)

#![allow(unused)]
fn main() {
#[derive(Serialize, Deserialize)]
pub struct SecretKeyFormat {
    pub ec_algorithm: ECAlgorithm,
    pub pq_algorithm: PQAlgorithm,
    pub dh_algorithm: DHAlgorithm,
    pub kem_algorithm: KEMAlgorithm,
    #[serde(with = "secret_vec_serde")]
    pub master_seed: SecretVec<u8>,
    #[serde(skip_serializing_if = "Option::is_none", flatten)]
    pub encryption_metadata: Option<EncryptionMetadataFormat>,
}
}
  • master_seed: the root secret (raw or encrypted).

  • encryption_metadata: optional; only present if the seed is encrypted with a password. Contains either:

    • pkdf_metadata – information about the password-based key derivation function (algorithm, salt)

    • kem_metadata – for hybrid KEM-based wrapping of the seed (optional).

Key points:

  • If encryption_metadata.pkdf_metadata is present, SARE will attempt to decrypt the seed using AES Key Wrap with the key derived via the PKDF.

  • If encryption_metadata.pkdf_metadata is absent, the seed is raw and used directly.

BSON Representation

  • Stored as a standard BSON document:
{
  "ec_algorithm": "EC_ALGO_NAME",
  "pq_algorithm": "PQ_ALGO_NAME",
  "dh_algorithm": "DH_ALGO_NAME",
  "kem_algorithm": "KEM_ALGO_NAME",
  "master_seed": "<raw or encrypted bytes>",
  "encryption_metadata": {
      "pkdf_metadata": {
          "pkdf_algorithm": "PBKDF2 | Argon2 | ...",
          "pkdf_salt": "<salt bytes>"
      },
      "kem_metadata": { ... } // optional
  }
}
  • The encryption_metadata field is optional.

  • Raw seeds omit encryption_metadata.

PEM Representation

  • The entire BSON (raw or encrypted) is Base64-encoded into PEM:
-----BEGIN SARE MASTER KEY-----
<base64-encoded BSON or encrypted seed>
-----END SARE MASTER KEY-----
  • Can be imported/exported via CLI or programmatic interfaces.

Encrypted Master Keys

  1. Password Key Derivation

    • If a password is provided, SARE uses the PKDF algorithm specified in pkdf_metadata to derive an AES-KW key.

    • Example PKDFs: PBKDF2, Argon2.

  2. AES Key Wrap

    • The derived key encrypts (wraps) the master seed, producing a protected master_seed in SecretKeyFormat.
  3. Optional KEM Wrapping

    • For hybrid setups, kem_metadata can store a KEM-based encrypted seed instead of or in addition to PKDF.
  4. Decryption Logic

    • If encryption_metadata.pkdf_metadata exists, SARE derives the AES-KW key and unwraps the seed.

    • Otherwise, the seed is treated as raw.

Fingerprint Calculation

  • The fingerprint is SHA256 over the master_seed bytes:
#![allow(unused)]
fn main() {
impl SecretKeyFormat {
    pub fn calculate_fingerprint(master_seed: SecretVec<u8>) -> Vec<u8> {
        let mut hasher = Sha256::new();
        hasher.update(master_seed.expose_secret());
        let fingerprint: [u8; 32] = hasher.finalize().into();
        fingerprint[..=16].to_vec()
    }
}
}
  • Used to uniquely identify the master key without exposing the seed.

FullChain Public Keys

A FullChain Public Key in SARE combines both signature and encryption public keys into a single, exportable structure. It is used to verify signatures and encrypt data for the holder of the corresponding master key.

Structure

The full chain contains two main components:

#![allow(unused)]
fn main() {
#[derive(Serialize, Deserialize, Clone)]
pub struct FullChainPublicKeyFormat {
    pub signature_public_key: SignaturePublicKeyFormat,
    pub encryption_public_key: EncryptionPublicKeyFormat,
}
}

Signature Public Key (SignaturePublicKeyFormat)

  • Combines classical elliptic-curve (EC) and post-quantum (PQ) algorithms:
#![allow(unused)]
fn main() {
pub struct SignaturePublicKeyFormat {
    pub ec_algorithm: ECAlgorithm,
    pub pq_algorithm: PQAlgorithm,
    pub ec_public_key: Vec<u8>,
    pub pq_public_key: Vec<u8>,
}
}
  • Both EC and PQ signatures must verify successfully for a message to be trusted.

Encryption Public Key (EncryptionPublicKeyFormat)

  • Combines Diffie-Hellman (DH) and hybrid KEM algorithms:
#![allow(unused)]
fn main() {
pub struct EncryptionPublicKeyFormat {
    pub dh_algorithm: DHAlgorithm,
    pub kem_algorithm: KEMAlgorithm,
    pub dh_public_key: Vec<u8>,
    pub kem_public_key: Vec<u8>,
}
}
  • Used for hybrid KEM-based key agreement to encrypt secrets for this key holder.

Export Formats

BSON

  • The full chain can be encoded as BSON:
{
  "signature_public_key": {
    "ec_algorithm": "EC_ALGO",
    "pq_algorithm": "PQ_ALGO",
    "ec_public_key": "<bytes>",
    "pq_public_key": "<bytes>"
  },
  "encryption_public_key": {
    "dh_algorithm": "DH_ALGO",
    "kem_algorithm": "KEM_ALGO",
    "dh_public_key": "<bytes>",
    "kem_public_key": "<bytes>"
  }
}

PEM

  • Encoded as a standard PEM block:
-----BEGIN SARE FULLCHAIN PUBLIC KEY-----
<base64-encoded BSON>
-----END SARE FULLCHAIN PUBLIC KEY-----

Fingerprint

The fingerprint uniquely identifies a full chain public key and is derived deterministically from all contained public key components.

#![allow(unused)]
fn main() {
impl FullChainPublicKeyFormat {
    pub fn calculate_fingerprint(&self) -> [u8; 32] {
        let mut hasher = Sha256::new();

        // EC signature component
        hasher.update(self.signature_public_key.ec_algorithm.to_string().as_bytes());
        hasher.update(&self.signature_public_key.ec_public_key);

        // PQ signature component
        hasher.update(self.signature_public_key.pq_algorithm.to_string().as_bytes());
        hasher.update(&self.signature_public_key.pq_public_key);

        // DH encryption component
        hasher.update(self.encryption_public_key.dh_algorithm.to_string().as_bytes());
        hasher.update(&self.encryption_public_key.dh_public_key);

        // KEM encryption component
        hasher.update(self.encryption_public_key.kem_algorithm.to_string().as_bytes());
        hasher.update(&self.encryption_public_key.kem_public_key);

        let fingerprint: [u8; 32] = hasher.finalize().into();
        fingerprint
    }
}
}

Notes:

  • Uses SHA-256 over all algorithm identifiers and public key bytes.

  • Ensures unique identification of each full chain public key.

  • Safe to share publicly, as it contains only public information.

Encryption and Decryption in SARE

SARE provides both symmetric and asymmetric encryption mechanisms to protect data, combining modern cryptographic primitives with flexible key management.

Underlying Algorithms

Currently, SARE supports the following primary algorithms:

  • XChaCha20-Poly1305: Used for symmetric encryption of file contents. Provides strong authenticated encryption with a large nonce space.

  • AES-256 Key Wrap (AES-KW): Used for securely wrapping smaller cryptographic keys, ensuring confidentiality and integrity of key material.

Other algorithms such as AES-GCM are listed but not implemented yet.

Key Derivation for Encryption

SARE separates the encryption algorithm from the key derivation process, allowing flexibility and additional security measures:

  • Symmetric encryption from passwords:
    A passphrase is converted into a cryptographic key using a password-based key derivation function (PKDF). This ensures that even weak passwords are transformed into keys that are safe for encryption.

  • Asymmetric encryption for recipients:
    Using a Hybrid Key Encapsulation Mechanism (HybridKEM), SARE generates two shared secrets between the sender and the recipient. These secrets are combined and expanded via an HKDF to produce the final symmetric encryption key.

    Note: Even in asymmetric scenarios, the underlying encryption algorithm remains symmetric (e.g., XChaCha20-Poly1305), providing efficiency and post-quantum security from the key exchange.

Encryption Metadata and File Headers

Encrypted files in SARE are not just raw ciphertext—they include structured metadata to support decryption, verification, and key management:

  • Encryption metadata includes:

    • The algorithm used for encrypting the file (e.g., XChaCha20-Poly1305).

    • Nonces for stream encryption.

    • Optional key encapsulation metadata (for asymmetric encryption).

    • Optional PKDF metadata (for password-based encryption).

  • File header:
    Every encrypted file contains a header that embeds this encryption metadata along with other metadata, such as digital signatures or comments. This allows SARE to fully describe the encrypted content and recover the key material without requiring external parameters.

The encryption metadata is a defined format within the header but has its own documentation for further details.

Encrypting and Decrypting Data

  • Symmetric encryption (e.g., with a passphrase) involves:

    1. Deriving a key via PKDF.

    2. Initializing an Encryptor with the derived key and the chosen algorithm.

    3. Writing the structured file header, followed by the encrypted content.

  • Asymmetric encryption (e.g., for a recipient) involves:

    1. Generating shared secrets via HybridKEM.

    2. Deriving a symmetric encryption key via HKDF.

    3. Encrypting the file content using XChaCha20-Poly1305.

    4. Embedding key encapsulation and encryption metadata into the file header.

  • Decryption mirrors these processes:

    1. Reading and decoding the file header to obtain metadata.

    2. Recovering the encryption key (via PKDF or HybridKEM + HKDF).

    3. Decrypting the content with the chosen symmetric algorithm.


This design ensures that SARE encrypted files are self-describing, secure against modern attacks, and compatible with both password-based and recipient-based key management workflows.

Key Derivation Functions (KDFs) in SARE

In SARE, cryptographic keys are derived systematically to ensure security and uniqueness across different algorithms and use cases. Two main categories of KDFs are employed: HKDF for general key derivation and password-based KDFs (PKDFs) for deriving keys from user-supplied secrets like passwords.

HKDF-Based Key Derivation

SARE uses the HMAC-based Key Derivation Function (HKDF) to expand secret material into cryptographic keys. The specific hash function used depends on the desired key size:

  • 32-byte keys (256-bit): Use SHA-256.
  • 64-byte keys (512-bit): Use SHA-512.

Each HKDF derivation includes algorithm-specific magic bytes to ensure that even if the same input material is used across multiple algorithms, the resulting keys are unique. These magic bytes are prepended or mixed into the input seed when deriving keys for different algorithms.

Example usage:

Key size: 32 bytes → SHA-256 HKDF
Magic bytes: [25, 85, 210, 14] (for Ed25519, for instance)

Key size: 64 bytes → SHA-512 HKDF
Magic bytes: [104, 7, 0, 0] (for Kyber768, for instance)

This mechanism guarantees that each derived key is tied not only to the input seed but also to the cryptographic algorithm and context, preventing key collisions.

Password-Based Key Derivation (PKDF)

For symmetric encryption or key wrapping, SARE derives keys from passwords using scrypt. This function applies configurable parameters to increase computational cost and memory usage, defending against brute-force attacks.

Typical flow:

  1. Generate a random salt (8 bytes by default).
  2. Apply scrypt with specified parameters (N, r, p) to the password and salt.
  3. Extract a key of the required length.

Scrypt ensures that even weak passwords produce keys resistant to offline attacks, and the salt guarantees that identical passwords produce different keys.

Example parameters:

N = 2^5 = 32
r = 8
p = 1

Derived keys from PKDFs can then be safely used for:

  • Symmetric encryption
  • Key wrapping for secure storage
  • Hybrid cryptographic constructions alongside HKDF-derived keys

Summary

  • HKDF: Produces algorithm-specific keys using magic bytes, keyed on SHA-256 or SHA-512 depending on the output size.
  • PKDF (scrypt): Converts passwords into cryptographic keys, incorporating salt and computationally intensive parameters to protect against brute-force attacks.
  • All derived keys are unique per algorithm and purpose due to the combination of input material, salt, and magic bytes.

Certificates in SARE

SARE uses certificates to provide verifiable proof about public keys and their status. Certificates in SARE are self-contained, cryptographically signed documents that are BSON-encoded and stored in PEM format in SARE CLI.

Types of Certificates

SARE currently supports two main types of certificates:

1. Validation Certificates

  • These certificates are attached to a full-chain public key.

  • They indicate that a particular public key is valid and can be trusted within a SARE network.

  • Validation certificates include:

    • Issuer information (name and email)

    • Expiry date (optional)

    • Full-chain public key fingerprint (ensures the certificate is linked to a specific key)

  • Validation certificates are signed by a SARE master key to ensure authenticity.

2. Revocation Certificates

  • Used to indicate that a previously valid public key or certificate is no longer trustworthy.

  • Revocation certificates include:

    • Revocation date

    • Revocation reason (e.g., Compromised or NoReasonSpecified)

    • Full-chain fingerprint of the revoked public key

  • Revocation certificates are also signed with a SARE master key to prevent tampering.

Certificate Structure

All SARE certificates consist of:

  1. Issuer Metadata:

    • name: the name of the issuer

    • email: the email of the issuer

  2. Optional Expiry Date:

    • For validation certificates, defines when the certificate should no longer be considered valid
  3. Certificate Type (via CertificateType enum):

    • Validation: contains ValidationCertificateFormat with the full-chain public key fingerprint

    • Revocation: contains RevocationCertificateFormat with revocation details

  4. Signature:

    • Every certificate is cryptographically signed by the issuing master key.

    • SARE uses its internal SignatureHeaderFormat to encode the signature alongside the certificate data.

Encoding and Storage

  • Certificates are BSON-encoded, allowing structured storage of metadata and cryptographic information.

  • For portability and interoperability, certificates are stored in PEM format in SARE CLI. The PEM tag depends on the type:

    • Validation certificates: SARE VALIDATION CERTIFICATE

    • Revocation certificates: SARE REVOCATION CERTIFICATE

  • PEM format provides ASCII-armoring, making the certificates easy to transport, copy, and distribute.

Certificate Operations

SARE provides utilities to handle certificates:

  • Creation:

    • new_validation() — create a validation certificate attached to a public key

    • new_revocation() — create a revocation certificate specifying the revocation reason

  • Export:

    • Certificates can be exported as PEM files to any writable stream
  • Import:

    • PEM-encoded certificates can be imported and decoded into a SARE certificate object
  • Verification:

    • All certificates can be verified cryptographically using the attached signature
  • Accessing Data:

    • The certificate’s revocation or validation details can be accessed via helper methods

Notes

  • Both validation and revocation certificates are signed and verifiable, ensuring authenticity and integrity.

  • While SARE CLI uses PEM format for certificates, the underlying representation is BSON-encoded, consistent with other SARE formats like encrypted files and signatures.

  • Certificates are self-contained and portable, making them suitable for secure key management and revocation in a SARE environment.

SareDB in SARE-CLI

SareDB is a command-line specific component of SARE. It is not part of the core SARE library (sare-lib) and exists purely to facilitate local management of keys and recipients in SARE CLI.

⚠️ Note: SareDB is in an early stage and may evolve significantly in future versions.

Purpose

SareDB is designed to act as a lightweight, local database for storing:

  1. Master key associations

    • Links a master key identifier to associated keys and revocation certificates.

    • Each association is stored as a SareDBAssociatedKey object containing:

      • public_key_id — the associated public key ID

      • revocation_certificate_id — the linked revocation certificate ID

  2. Recipients

    • Tracks known recipients to simplify encryption workflows.

    • Stored as SareDBRecipient objects with:

      • fullchain_fingerprint — the recipient’s key fingerprint

      • Optional comment

      • date_added timestamp

Structure and Storage

  • Internally, SareDB uses two HashMaps:

    • key_associations: maps a master key ID to its associated key information.

    • recipients: maps a recipient identifier to recipient metadata.

  • The database is serialized and stored as a JSON file in the SARE directory, making it human-readable and easy to inspect.

  • version field allows for future upgrades or migrations to the database format.

Functionality

SareDB provides the following operations:

  1. Adding and updating keys

    • add_key_association(master_key_id, associated_key) inserts or updates a master key association.
  2. Adding recipients

    • add_recipient(recipient_id, recipient) adds a new recipient to the database.
  3. Retrieving information

    • get_key_association(master_key_id) returns an associated key if it exists.

    • list_recipients() returns all stored recipients.

  4. Persistence

    • import_from_json_file() loads the database from JSON or returns an empty database if the file does not exist.

    • save_to_json_file() writes the current database to JSON for persistence between CLI sessions.

Notes

  • SareDB is primarily intended for local, per-user storage. It is not a cryptographically secure or distributed database.

  • Since SARE CLI is still under active development, the structure, storage format, and supported fields may change. Users should not rely on SareDB as a stable long-term API.

Keep The Project Alive ❤️

Support Sare's Development

Sare is an open-source project driven by community contributions and support. If you find Sare valuable and would like to contribute to its continued development and improvement, consider making a donation. Your support helps us maintain and enhance Sare for the benefit of all users.

Cryptocurrency Donations

You can support us by making donations in various cryptocurrencies. Your contributions help support ongoing development, and ensure the sustainability of the project.

  • Monero (XMR):

    8AF4Lybz7QwiucdYW2szsgiqTHdBp5kjZSSRm6ddzd5363S6n4jixpkACGMLx5JWZnUR5MnGF7cMoidjppruAvLvMe2ovHZ
    
  • Bitcoin (BTC):

    bc1qdzdlytujxn3l02vdt90xx5pkqlezxpuucs6fmm
    
  • Ethereum (ETH):

    0x9E00DC6bE0d07bDB5Ff8B62593a0193913c9B595
    
  • Bitcoin Cash (BCH):

    qzmxuv82j9n2zlxkylrz882yk9e50wvzz5a6hqy2dc
    
  • Dash:

    XamhGMK5XM1wPKqSiF8HACJsToVmW4jMGL
    
  • Dogecoin (DOGE):

    DBEaZAbo5tDk7LuXd7pCkhQMa2h8kBgVbS
    
  • Litecoin (LTC):

    ltc1qrex5xq3px5qn9vjplfkmvzf7sweks3r4skxe5k
    
  • Matic (MATIC):

    0x9E00DC6bE0d07bDB5Ff8B62593a0193913c9B595
    
  • TON (Free TON):

    EQAjMitBSLjcl4DwthElddvuRSW3N-Dvd0HX-RkGMUVsC9sT
    
  • TRON (TRX):

    TUT762nFQQRoXvDe1Z72p3kKH9uY3XZCg9
    
  • Zcash (ZEC):

    t1WbpyRF7sXidefAzA5Vb922dsR3PLe9bRZ
    
  • Stellar (XLM):

    GDT7GJS6U3N2CCWNQAORW2EJ2XFDCUGXOGZXEMGKOP6ILQ77ZIPN3ET4
    
  • Cosmos (ATOM):

    cosmos1pwu953l57000n9hleerzm3hzaclldhpxf86l32
    
  • Solana (SOL):

    5TT1URTgmnXziXXS1avgV4uF7Dwj5f3MNHLPcZtQKVk9
    
  • Ravencoin (RVN):

    RLN8CqRzgDajY77Sd3xYREVLheTYEb7rWc
    

Your contributions are highly appreciated, and they play a crucial role in the ongoing development of Sare. Thank you for supporting the project!