Skip to content

Security Model & Best Practices

Eldric Arlo Bennett edited this page Nov 14, 2025 · 1 revision

Oracipher Core: Security Model & Developer Best Practices

This document outlines the security model of the Oracipher Core library and provides essential best practices for developers. Adhering to these guidelines is critical for building secure applications on top of the library.


1. The Oracipher Core Security Model

The library is designed to be a secure cryptographic kernel, but its overall security relies on a partnership between the library's guarantees and the developer's secure implementation.

1.1 Threat Model

A threat model defines what a system is designed to protect against and, just as importantly, what is outside its scope.

Oracipher Core is designed to protect against:

  • Network Eavesdropping: All data encrypted by the library is protected by XChaCha20-Poly1305, ensuring confidentiality even if an attacker captures all network traffic.
  • Data Tampering (Man-in-the-Middle Attacks): The use of Authenticated Encryption (AEAD) and signed OCSP responses ensures that any modification to encrypted data or certificate status information in transit will be detected, causing the operation to fail.
  • Server-Side Data Breaches: If a server storing data encrypted by Oracipher Core is compromised, the data payloads remain secure as the server does not have access to the users' private keys.
  • Offline Password Cracking: If a database of password hashes is stolen, the combination of a unique salt per user and the mandatory, system-wide security pepper makes pre-computed rainbow table attacks and low-cost brute-force attacks against the hashes computationally infeasible.

Oracipher Core is NOT designed to protect against:

  • Compromised Client Endpoints: The library cannot protect against threats on the user's machine, such as malware, keyloggers, or memory-scraping viruses. The security of the client environment is the developer's responsibility.
  • Insecure Environment Variable Injection: The security of the HSC_PEPPER_HEX environment variable depends on the security of the deployment environment. The library trusts that the environment provides this secret securely.
  • Compromised Certificate Authority (CA): The entire PKI trust model relies on the integrity of the CA. If the CA's private key is stolen, an attacker can issue fraudulent certificates and impersonate any user.
  • Physical Coercion or User Negligence: The library cannot protect against a user being forced to give up their keys or a user mishandling their private key files.

1.2 The Security Responsibility Pact

Security is a shared responsibility between the library and the application developer.

The Library's Responsibilities (Our Guarantees):

  • Correct Cryptographic Implementation: We guarantee that the library correctly uses the underlying cryptographic primitives from libsodium and OpenSSL according to modern best practices.
  • Secure Internal Memory Management: We guarantee that all internal, long-term secrets (like private keys and the security pepper) are handled exclusively in protected, non-swappable memory and are securely wiped upon release.
  • Fail-Closed Policy Enforcement: We guarantee that any ambiguity or failure during a critical security check (like OCSP validation) will result in the operation failing securely.
  • Safe API Contract: We provide a clear API that is resistant to common misuse patterns (e.g., automatic nonce management in standard APIs).

The Developer's Responsibilities (Your Obligations):

  • Protect Private Keys at Rest: You are responsible for securing user private key files on the filesystem with strict permissions.
  • Securely Manage the Security Pepper: You are responsible for generating, storing, and securely injecting the HSC_PEPPER_HEX environment variable in your production environment.
  • Check Every Return Code: You are responsible for checking the return value of every library function call and handling failures appropriately by aborting the sensitive operation.
  • Secure Your Certificate Authority: You are responsible for the security and operational integrity of your CA, which is the root of your trust model.
  • Handle Plaintext Securely: You are responsible for using the provided secure memory functions (hsc_secure_alloc/hsc_secure_free) for any sensitive plaintext data your application handles.

1.3 Deep Dive: The Security Pepper

The use of a global security pepper is a mandatory, non-negotiable part of the library's KDF security model.

  • What It Is: A secret value, unique to your entire service or application, that is mixed with user passwords before they are processed by Argon2id.
  • Why It's Critical: It defeats offline attacks on a stolen password hash database. An attacker with the database cannot begin password-guessing or rainbow table attacks without also knowing the pepper. It effectively gives every password in your system a unique, high-entropy secret component that the attacker does not have.
  • How to Manage in Production: The pepper must never be hardcoded or stored in a configuration file alongside the application code. It must be injected into the application's environment at runtime. Secure methods include:
    • Container/Orchestration Secrets: Using tools like Docker Secrets, Kubernetes Secrets, or HashiCorp Vault.
    • Cloud Provider Secret Managers: Using services like AWS Secrets Manager, Google Cloud Secret Manager, or Azure Key Vault.
    • Generating a Secure Pepper:
      # Use OpenSSL to generate a cryptographically secure 32-byte (256-bit) pepper in hex format
      openssl rand -hex 32

2. Developer Best Practices

Violating these practices can completely undermine the security guarantees provided by the library.

2.1 Critical: Manage the Library Lifecycle Correctly

  • DO: Call hsc_init() once at the very beginning of your main function.
  • DO: Call hsc_cleanup() once just before your application exits.
  • DO NOT: Call any other library function before hsc_init() has successfully returned HSC_OK.
  • DO NOT: Forget to call hsc_cleanup(), as this will leave the security pepper lingering in memory.

2.2 Critical: Check Every Return Code

  • DO: Check the return value of every function call against HSC_OK.
  • DO NOT: Assume an operation succeeded. Ignoring a failure from a function like hsc_verify_user_certificate or hsc_aead_decrypt can lead to you trusting an invalid identity or acting on unauthenticated data.
// WRONG - Ignores failure, proceeds with a potentially untrusted key
int ignored_result = hsc_verify_user_certificate(cert, ca, "user");
hsc_extract_public_key_from_cert(cert, public_key); // This is now a dangerous operation

// RIGHT - Aborts on failure
if (hsc_verify_user_certificate(cert, ca, "user") != HSC_OK) {
    // Log the error and immediately abort the entire workflow.
    return;
}
// It is now safe to trust this certificate and extract the key.
hsc_extract_public_key_from_cert(cert, public_key);

2.3 Use Secure Memory for All Sensitive Plaintext

The library exposes hsc_secure_alloc and hsc_secure_free for handling sensitive data in your application's memory.

  • DO: Use hsc_secure_alloc to store sensitive plaintext that your application must temporarily handle, such as:
    • A decapsulated session key.
    • The contents of a fully decrypted file before processing.
    • A user's password before passing it to hsc_derive_key_from_password.
  • DO: Call hsc_secure_free on the pointer as soon as the sensitive data is no longer needed to minimize its exposure time in memory.

2.4 Protect Private Key Files at Rest

  • DO: Set strict filesystem permissions for private key files (e.g., chmod 400 my_user.key on Linux/macOS).
  • DO NOT: Store private keys in publicly accessible locations, check them into version control, or embed them directly in application bundles.
  • CONSIDER: For high-security environments, store private keys in a Hardware Security Module (HSM).

2.5 Avoid Misuse of Expert-Level APIs

  • DO NOT: Use hsc_aead_encrypt_detached unless absolutely necessary for a specific protocol. If you do, you are responsible for nonce management. Nonce reuse with the same key is a catastrophic failure that destroys confidentiality. Always generate a unique nonce for every encryption using hsc_random_bytes.
  • DO: Prefer the standard hsc_aead_encrypt and stream APIs, which handle nonces safely and automatically.

Security Deployment Checklist

  • Is hsc_init() called at startup and hsc_cleanup() at shutdown?
  • Is the HSC_PEPPER_HEX environment variable generated securely and injected into my production environment without being logged or stored in version control?
  • Am I checking the return code of every Oracipher Core function call against HSC_OK?
  • Are my users' private key files protected with strict filesystem permissions (400 or 600)?
  • Is my CA private key secured (preferably offline), and do I have a defined certificate revocation process?
  • Am I using hsc_secure_alloc and hsc_secure_free for all sensitive plaintext my application code handles?