← Blog
Immutable Backups with Airgapper

Immutable Backups with Airgapper

goreactcryptographybackupssecurityopen-source

Your backups are only as secure as whoever holds the encryption key. If one person has the key, one person can be compromised. One disgruntled employee. One stolen laptop. One phishing email. Game over.

I built Airgapper to fix this: a consensus-based encrypted backup system where no single person can decrypt alone. The encryption key is split across multiple trusted parties using Shamir’s Secret Sharing, and restoration requires a quorum to reassemble it.

Why Traditional Backups Fall Short

Most backup solutions nail the mechanics. deduplication, compression, incremental snapshots. But they treat key management as an afterthought. You end up with one of these:

  • Single key holder. One person (or one server) has the decryption key. Single point of failure.
  • Shared password. Multiple people know the same password. No accountability, no revocation.
  • Key escrow. A third party holds your key. Now you’re trusting them instead.

The core problem: access control for backups is binary. You either can decrypt or you can’t. There’s no middle ground that says “you need 3 out of 5 people to agree before this data is unlocked.”

Airgapper introduces that middle ground.

Shamir’s Secret Sharing: The Core Idea

Shamir’s Secret Sharing (SSS) is a cryptographic technique published by Adi Shamir in 1979. The concept is elegant: split a secret into n shares such that any k shares can reconstruct it, but k-1 shares reveal absolutely nothing.

It works by encoding the secret as the constant term of a random polynomial of degree k-1 over a finite field. Each share is a point on that polynomial. With k points, you can use Lagrange interpolation to recover the polynomial (and the secret). With fewer points, there are infinitely many polynomials that fit. you learn nothing.

Here’s how it flows in Airgapper:

graph TD
    A["🔑 Generate Encryption Key"] --> B["📐 Create Random Polynomial<br/>degree k-1 over GF(256)"]
    B --> C["✂️ Evaluate at n Points<br/>Generate n Shares"]
    C --> D1["👤 Share 1 → Key Holder A"]
    C --> D2["👤 Share 2 → Key Holder B"]
    C --> D3["👤 Share 3 → Key Holder C"]
    C --> D4["👤 Share n → Key Holder n"]

    D1 & D2 & D3 --> E["🤝 k Holders Submit Shares"]
    E --> F["📈 Lagrange Interpolation"]
    F --> G["🔓 Reconstruct Encryption Key"]
    G --> H["📦 Decrypt & Restore Backup"]

    style A fill:#1a1a2e,stroke:#e94560,color:#fff
    style G fill:#1a1a2e,stroke:#00d2ff,color:#fff
    style H fill:#0f3460,stroke:#00d2ff,color:#fff

Airgapper implements SSS over GF(256). the same finite field used in AES. Each byte of the encryption key is split independently, and the arithmetic uses the irreducible polynomial x⁸+x⁴+x³+x+1. The implementation is in both Go (backend) and TypeScript (frontend), and both produce compatible shares.

Architecture

Airgapper has two roles: owner (who creates and manages the vault) and host (key holders who each store a share). The system uses a Go backend for cryptographic operations and storage management, with a React frontend for the management UI.

graph TB
    subgraph Owner["Owner Node"]
        FE["React Frontend<br/>Vault Management UI"]
        API["Go API Server<br/>Connect-RPC"]
        SSS_E["SSS Engine<br/>GF(256) Arithmetic"]
        Restic["Restic Integration<br/>Encrypted Snapshots"]
        Consent["Consent Manager<br/>Request Lifecycle"]
        Policy["Policy Engine<br/>Ed25519 Signing"]
    end

    subgraph Host1["Host Node (Key Holder)"]
        H1_FE["React Frontend"]
        H1_API["Go API Server"]
        H1_Share["Local Share Storage"]
        H1_Storage["Append-Only Storage Server"]
    end

    subgraph Host2["Host Node (Key Holder)"]
        H2_FE["React Frontend"]
        H2_API["Go API Server"]
        H2_Share["Local Share Storage"]
    end

    FE --> API
    API --> SSS_E
    API --> Restic
    API --> Consent
    API --> Policy
    Restic -->|"Encrypted Backups"| H1_Storage

    Consent -->|"Restore Request"| H1_API
    Consent -->|"Restore Request"| H2_API
    H1_API -->|"Approved + Share"| Consent
    H2_API -->|"Approved + Share"| Consent

    style Owner fill:#1a1a2e,stroke:#e94560,color:#fff
    style Host1 fill:#16213e,stroke:#00d2ff,color:#fff
    style Host2 fill:#16213e,stroke:#00d2ff,color:#fff

Key components:

  • SSS Engine. Polynomial evaluation and Lagrange interpolation over GF(256). Handles key splitting and reconstruction.
  • Consent Manager. Manages the lifecycle of restore and deletion requests. Tracks approvals, denials, and expiry (requests expire after 24 hours).
  • Policy Engine. Ed25519 signing for owner/host identity verification. Policies define the rules of the vault (threshold, key holders, permissions).
  • Restic Integration. Airgapper wraps restic for actual backup operations. Restic handles deduplication, compression, and encrypted snapshots. Airgapper controls the key.
  • Append-Only Storage. Host nodes can run a storage server that only accepts new data. Deletes are blocked, making backups immutable at the storage layer. Data blobs are hash-verified on upload.

The Consensus Flow

Here’s what actually happens when someone needs to restore data:

  1. Owner creates a restore request. specifying the snapshot and reason.
  2. Request is sent to all key holders. each holder sees the request in their UI.
  3. Key holders independently decide. they can approve (releasing their share) or deny.
  4. Threshold met. once k holders approve, the system has enough shares to reconstruct the encryption key via Lagrange interpolation.
  5. Restore proceeds. the key is reconstructed in memory, used to decrypt the restic snapshot, and then discarded.

No single person. not even the vault owner. can decrypt alone. The key only exists in its complete form for the brief moment during restoration.

Why Immutability Matters

Airgapper’s host nodes support append-only storage mode. Once a backup is written, it cannot be modified or deleted through the storage API. This protects against:

  • Ransomware. An attacker who compromises the owner node can’t delete or encrypt the backups stored on host nodes.
  • Insider threats. A rogue admin can’t silently wipe backup history.
  • Accidental deletion. Fat fingers can’t destroy your safety net.

Deletion requires its own consensus flow. a separate deletion request that key holders must approve, with cryptographic signatures proving identity. Even destroying data requires group agreement.

Use Cases

Business continuity. Split backup keys across your founding team. If the company’s infrastructure is compromised, no single attacker gains access. Recovery requires the team to come together.

Regulatory compliance. For data that requires multi-party access controls (think financial records, healthcare data), SSS provides a cryptographic guarantee that’s stronger than access control lists.

Dead man’s switch. Configure Airgapper with a heartbeat system. If the owner stops checking in, the system can notify key holders and initiate an emergency recovery flow. Your data doesn’t die with you.

Personal data protection. Split your personal encryption keys across family members or trusted friends. Your data stays accessible to the people you choose, but only when they cooperate.

What I Learned Building This

GF(256) arithmetic is satisfying. There’s something deeply elegant about finite field math. Multiplication via log/antilog tables, the way irreducible polynomials create closed algebraic structures. it’s beautiful once it clicks.

Consensus systems are hard. The cryptography was the easy part. The hard part is the UX: how do you make non-technical key holders understand what they’re approving? How do you handle the case where someone loses their share? The social layer of a consensus system is where the real complexity lives.

Restic is excellent. I chose to wrap restic rather than build backup mechanics from scratch, and I’m glad I did. It handles deduplication, compression, and snapshot management extremely well. Airgapper’s job is key management and consensus. not reinventing backup infrastructure.

Current Status

Airgapper is open source and functional for local/self-hosted use. The security audit identified areas to harden before production use (API authentication, TLS, encrypted config storage), which are actively being addressed. The core SSS implementation is mathematically verified and correct.

Check it out: github.com/lcrostarosa/airgapper

If you’re interested in the cryptography, the SSS implementation in internal/sss/sss.go is well-commented and a good reference for GF(256) arithmetic in Go.