Skip to content

How Secure LSL Works

A neuroscientist-friendly explanation of the encryption, without requiring a cryptography PhD.


The Big Picture

When you stream EEG data across your lab network, that data normally travels as plain numbers that anyone on the network can read. Secure LSL wraps that data in encryption so that only the intended recipient can read it.

flowchart LR
    subgraph Before["Without Secure LSL"]
        A1[EEG Amplifier] -->|"Plain data<br/>Anyone can read"| B1[Network]
        B1 -->|"Plain data"| C1[LabRecorder]
    end
flowchart LR
    subgraph After["With Secure LSL"]
        A2[EEG Amplifier] -->|"Encrypted<br/>Looks like noise"| B2[Network]
        B2 -->|"Encrypted"| C2[LabRecorder]
        C2 -->|"Decrypts to<br/>original data"| D2[Your Recording]
    end

Two Layers of Protection

Secure LSL provides two complementary protections:

1. Device Authentication (Who are you?)

Before any data flows, devices prove their identity using digital signatures. Each device has a unique cryptographic key pair:

  • Private key: Stays secret on the device (like a password)
  • Public key: Shared freely (like a username)

When your EEG amplifier connects to LabRecorder, they exchange public keys and each proves they hold the matching private key. This prevents:

  • Unauthorized devices from connecting
  • Attackers from impersonating your equipment
  • "Man-in-the-middle" attacks where someone intercepts your connection

Analogy: ID Cards

Think of this like showing ID at a security checkpoint. The public key is your photo ID, and the private key is your ability to match the photo. You can show your ID to anyone, but only you can prove you're the person in the photo.

2. Data Encryption (Keep it secret)

Once devices are authenticated, all data is encrypted using a session key that only those two devices know. This means:

  • Eavesdroppers see only random-looking bytes
  • Even if someone captures your network traffic, they can't read your biosignals
  • Each connection uses a different key, so compromising one doesn't affect others
flowchart TD
    subgraph Outlet["EEG Amplifier"]
        O1[Raw EEG Data] --> O2[Encrypt with<br/>session key]
        O2 --> O3[Encrypted packet]
    end

    O3 -->|Network| I1

    subgraph Inlet["LabRecorder"]
        I1[Encrypted packet] --> I2[Decrypt with<br/>session key]
        I2 --> I3[Original EEG Data]
    end

The Cryptographic Algorithms

We use algorithms trusted by banks, governments, and security experts worldwide:

Ed25519 for Identity

Ed25519 is a digital signature algorithm that:

  • Creates compact 32-byte public keys (fits in a single network packet)
  • Verifies signatures in microseconds (no delay for real-time systems)
  • Is resistant to known attacks, including some quantum computing threats
  • Is used by OpenSSH, Signal, and countless security-critical systems

ChaCha20-Poly1305 for Encryption

ChaCha20-Poly1305 is an authenticated encryption algorithm that:

  • Encrypts data so only the key holder can read it (ChaCha20)
  • Detects any tampering with the encrypted data (Poly1305)
  • Runs 3-4x faster than AES on devices without hardware acceleration (like Raspberry Pi)
  • Uses less power on mobile and embedded devices
  • Is used by Google, Cloudflare, and most modern TLS connections

Why not AES?

AES-GCM is excellent when hardware acceleration is available (AES-NI on Intel chips). But many biosignal devices use ARM processors without this acceleration. ChaCha20 provides equivalent security with better performance across all platforms.


Authenticated Encryption: Why It Matters

Traditional encryption only hides data. An attacker could still modify the encrypted bytes, potentially causing unpredictable results when decrypted.

Authenticated encryption solves this by adding a 16-byte authentication tag to each packet. This tag is like a tamper-evident seal:

flowchart LR
    subgraph Packet["Encrypted Packet"]
        direction LR
        A[Nonce<br/>8 bytes] --> B[Encrypted Data<br/>variable]
        B --> C[Auth Tag<br/>16 bytes]
    end

When decrypting:

  1. First, verify the authentication tag
  2. If verification fails → reject the packet entirely (tampered or corrupted)
  3. If verification passes → decrypt and use the data

This means:

  • Bit flips detected: Even changing a single bit is caught
  • Truncation detected: Shortened packets are rejected
  • Injection detected: Added bytes are rejected
  • No silent corruption: You never get garbage data disguised as real samples

Validation Result

In testing, we modified 10,000 packets in various ways (single-bit flips, multi-byte changes, truncation). 100% were detected and rejected.


Replay Attack Prevention

An attacker could capture legitimate encrypted packets and re-transmit them later. While they can't read or modify the data, replaying old packets could:

  • Corrupt your recording with duplicate samples
  • Confuse real-time processing systems
  • Inject false triggers or events

Secure LSL prevents this using nonces (numbers used once):

sequenceDiagram
    participant Outlet
    participant Inlet

    Outlet->>Inlet: Packet with nonce=1
    Outlet->>Inlet: Packet with nonce=2
    Outlet->>Inlet: Packet with nonce=3

    Note over Inlet: Attacker replays packet with nonce=2

    Outlet->>Inlet: Packet with nonce=4
    Inlet--xInlet: Reject! nonce=2 already seen

Each packet includes a monotonically increasing nonce. The inlet tracks seen nonces and rejects any that aren't newer than the last. This provides:

  • Replay detection: Old packets are caught
  • Out-of-order tolerance: A sliding window allows minor reordering
  • 64-bit counter: Supports 584 million years of operation at 1000 packets/second

Session Keys and Forward Secrecy

Your device's Ed25519 key is long-lived (you generate it once). But what if it's ever compromised?

Secure LSL protects against this with session keys:

  1. When two devices connect, they perform a key exchange to create a shared secret
  2. This secret is used to derive a session key that encrypts all data
  3. Session keys are rotated every 24 hours
  4. Session keys are never stored; they exist only in memory

This provides forward secrecy: even if an attacker eventually obtains your device's private key, they cannot decrypt recordings from past sessions that used different session keys.

flowchart TD
    subgraph Long-term["Long-term Identity (Ed25519)"]
        A[Device Private Key]
        B[Device Public Key]
    end

    subgraph Session["Session Keys (Ephemeral)"]
        C[Session Key 1<br/>Hours 0-24]
        D[Session Key 2<br/>Hours 24-48]
        E[Session Key 3<br/>Hours 48-72]
    end

    A --> C
    A --> D
    A --> E

    C -->|Encrypts| F[Recording Day 1]
    D -->|Encrypts| G[Recording Day 2]
    E -->|Encrypts| H[Recording Day 3]

    style C fill:#90EE90
    style D fill:#90EE90
    style E fill:#90EE90

The Unanimous Security Model

Secure LSL uses a "secure by default with unanimous opt-out" model:

  • If any device on your network has security enabled, all connections must be secure
  • Only if all devices explicitly disable security can they operate insecurely
  • Mixed environments are not allowed

This design:

  • Eliminates partial-security vulnerabilities
  • Prevents downgrade attacks
  • Simplifies compliance verification
  • Creates natural migration pressure toward full security
flowchart TD
    subgraph Valid["Valid Configurations"]
        A1[All Secure] -->|"✓ Works"| OK1[Encrypted streaming]
        A2[All Insecure] -->|"✓ Works"| OK2[Plain streaming]
    end

    subgraph Invalid["Invalid Configurations"]
        B1[Mixed] -->|"✗ Rejected"| ERR[Clear error message]
    end

    style OK1 fill:#90EE90
    style OK2 fill:#FFE4B5
    style ERR fill:#FFB6C1

Performance Impact

Encryption isn't free, but it's very cheap:

Platform Configuration Overhead Added Latency
Intel i7 Workstation 64ch @ 1000Hz 2.1% +0.3ms
Intel i5 Laptop 64ch @ 1000Hz 3.8% +0.5ms
Raspberry Pi 4 (ARM) 64ch @ 1000Hz 4.7% +0.9ms
Intel i7 Workstation 256ch @ 10kHz 3.2% +0.4ms

All measurements showed zero packet loss in 48-hour stress tests.

The sub-millisecond latency overhead is negligible for biosignal applications where synchronization requirements are typically in the 1-10ms range.


Summary

Layer Algorithm Protection
Identity Ed25519 Only authorized devices connect
Encryption ChaCha20 Data is unreadable to eavesdroppers
Integrity Poly1305 Tampering is detected immediately
Replay Nonce tracking Old packets can't be re-injected
Future Session keys Past recordings stay safe

All of this happens transparently inside the LSL library. Your code doesn't change.


Further Reading