DEV Community

KEERTHIVASAN S
KEERTHIVASAN S

Posted on

# Crypto-Agility Without the Cloud: I Built a Local-First Cryptographic Policy Engine

What if an application could change its cryptographic strategy without contacting a server, downloading a security policy, or depending on a cloud service?

That is the idea behind CryptoFlex.

CryptoFlex is a local-first crypto-agility policy engine for Python that makes cryptographic decisions entirely inside the application environment.

No network calls.

No telemetry.

No remote policy server.

No third-party decision-making service.

Just local cryptographic capabilities, local policy, and an application-defined security requirement.

🔐 Why local-first?

Most modern security systems are increasingly connected to external services.

But there are applications where that isn't desirable or even possible.

Consider:

  • Offline file-encryption tools
  • Desktop security applications
  • Embedded devices
  • Air-gapped environments
  • Local-first software
  • Systems with strict data-isolation requirements

In these environments, asking a remote service:

"Which cryptographic algorithm should I use?"

doesn't make much sense.

CryptoFlex is designed around a different idea:

              Application
                   │
                   ▼
          ┌─────────────────┐
          │    CryptoFlex   │
          │   Policy Engine │
          └────────┬────────┘
                   │
          LOCAL DECISION ONLY
                   │
       ┌───────────┼───────────┐
       ▼           ▼           ▼
    X25519     X25519 +     X25519 +
              ML-KEM-768   ML-KEM-1024
Enter fullscreen mode Exit fullscreen mode

The decision is made locally.

🧠 What makes CryptoFlex different?

CryptoFlex isn't trying to create a new cryptographic algorithm.

Instead, it sits above existing cryptographic primitives.

The project currently supports:

Profile Cryptographic sources Quantum-safe
classical_only X25519 No
hybrid_standard X25519 + ML-KEM-768 Yes
hybrid_high X25519 + ML-KEM-1024 Yes

The application doesn't have to hard-code one of these combinations throughout its architecture.

Instead, the PolicyEngine can select a profile based on local information such as:

  • Available cryptographic implementations
  • Security/performance constraints
  • A versioned local risk table

This is where the crypto-agility idea comes in.

🔄 From algorithm lock-in to crypto-agility

A tightly coupled application might look like:

key_exchange = X25519()
Enter fullscreen mode Exit fullscreen mode

The application now assumes X25519 everywhere.

If its security requirements change later, replacing the algorithm can become an architectural problem.

With a policy layer, the application can instead express something closer to:

constraint = Constraint.BALANCED
Enter fullscreen mode Exit fullscreen mode

CryptoFlex determines which supported profile satisfies that requirement.

Today that could mean:

X25519
Enter fullscreen mode Exit fullscreen mode

Tomorrow:

X25519 + ML-KEM-768
Enter fullscreen mode Exit fullscreen mode

And later:

X25519 + ML-KEM-1024
Enter fullscreen mode Exit fullscreen mode

The goal is to make the cryptographic policy replaceable without tightly coupling it to the rest of the application.

⚔️ Why hybrid cryptography?

CryptoFlex supports hybrid classical + post-quantum configurations.

For example:

X25519
   +
ML-KEM-768
   │
   ▼
Combined key material
   │
   ▼
HKDF
   │
   ▼
Root key
Enter fullscreen mode Exit fullscreen mode

The classical and post-quantum mechanisms contribute to the resulting key establishment.

But there is an important distinction:

CryptoFlex did not invent hybrid cryptography.

X25519, ML-KEM, and hybrid key-exchange designs already exist.

The focus of CryptoFlex is the local policy and orchestration layer around these established primitives.

🗂️ Local-first + migration-aware

Crypto-agility creates another interesting problem.

What happens when the default cryptographic policy changes?

Imagine:

2026
hybrid_standard
X25519 + ML-KEM-768
Enter fullscreen mode Exit fullscreen mode

Later:

Future
hybrid_high
X25519 + ML-KEM-1024
Enter fullscreen mode Exit fullscreen mode

What happens to files encrypted under the previous policy?

CryptoFlex addresses this with a versioned header format.

The header can preserve information about the cryptographic profile associated with the encrypted data.

So changing the current policy doesn't automatically mean rewriting every previously encrypted file.

This is an important part of making cryptographic migration practical.

🛡️ No silent security downgrade

Another design choice is how CryptoFlex handles unavailable PQC support.

If ML-KEM isn't available, the engine can fall back to:

classical_only
Enter fullscreen mode Exit fullscreen mode

But the decision exposes:

decision.degraded
decision.reason
Enter fullscreen mode Exit fullscreen mode

So the application can detect that the selected configuration is weaker than the preferred configuration.

For applications that don't want this fallback, CryptoFlex supports:

require_quantum_safe=True
Enter fullscreen mode Exit fullscreen mode

For example:

decision = engine.decide(
    Constraint.BALANCED,
    require_quantum_safe=True
)
Enter fullscreen mode Exit fullscreen mode

Instead of silently continuing with a classical configuration, the application can fail when its quantum-safe requirement cannot be satisfied.

🌐 No network dependency

This is probably the feature I care about most.

CryptoFlex does not depend on:

  • Cloud security services
  • Remote algorithm-selection APIs
  • Live threat feeds
  • Telemetry systems
  • Network connectivity

The risk table is bundled locally and can change through normal package releases.

That means the policy decision remains inside the application's security boundary.

🔑 What happens underneath?

CryptoFlex uses established libraries rather than implementing cryptographic mathematics itself.

The project uses:

  • cryptography for X25519 and HKDF
  • liboqs-python for ML-KEM

The combined key material is processed through HKDF.

Conceptually:

Classical shared secret
          +
PQC shared secret
          │
          ▼
        HKDF
          │
          ▼
      Root key
Enter fullscreen mode Exit fullscreen mode

The project follows established hybrid key-combination design principles rather than introducing a new cryptographic construction.

🐍 Using CryptoFlex

A basic example:

from cryptoflex import (
    PolicyEngine,
    Constraint,
    establish_keys,
    derive_root_key,
    recover_root_key
)

engine = PolicyEngine()

keyset = establish_keys(
    engine,
    constraint=Constraint.BALANCED
)

print(keyset.policy_decision.reason)

derived = derive_root_key(
    keyset.public_bundle
)

root_key = recover_root_key(
    keyset.private_handles,
    derived.header
)

assert root_key == derived.root_key
Enter fullscreen mode Exit fullscreen mode

The consuming application can then use the derived root key with its own encryption layer.

🎯 So what's actually unique?

CryptoFlex isn't claiming that any individual cryptographic primitive is new.

The interesting part is the combination of:

Local-first

*

Runtime cryptographic policy

*

Crypto-agility

*

Classical + post-quantum profiles

*

Migration-aware encrypted-data headers

*

Explicit degraded-state handling

All inside a Python library designed specifically around local/offline applications.

That's the problem I'm exploring.

⚠️ Current status

CryptoFlex is currently v0.1.0 and unaudited.

It is an early project, not a production-ready cryptographic library.

I built it to explore how applications could be designed for cryptographic migration without becoming permanently coupled to one cryptographic stack.

🚀 The project

GitHub:

https://github.com/keerthivasan-sankar/crypto_flex

I'm especially interested in feedback on the PolicyEngine architecture, local risk model, migration design, and API.

If you were building a crypto-agility layer for an offline/local application, what would you change?

Python #Cryptography #CyberSecurity #PostQuantum #PQC #CryptoAgility #OpenSource #SoftwareArchitecture #Privacy

Top comments (0)