Skip to content
Safe Signing

Signing Flow

Three-device signing architecture: Agent Host builds calldata, air-gap relay transfers unsigned TX bytes, isolated Signing Device signs with hardware wallet. Keys and internet never coexist.

The Threat Model explained why signing on a hot machine is dangerous. This page shows the physical architecture that eliminates those threats: three devices, strict role separation, and a one-way relay bridge.

Three devices

A
Agent Host
Networked machine. Runs agent, simulation, research. Has internet. No keys.
R
Air-Gap Relay
Dedicated relay device. Carries only unsigned/signed TX bytes. No state, no keys, no internet.
S
Signing Device
Air-gapped signer. No internet. Hardware wallet. Reviews and signs.

Step-by-step flow

AGENT HOST AIR-GAP RELAY SIGNING DEVICE 1 Build calldata + simulate 2 User reviews state diff 3 TX plan → air-gap relay 4 Decode, show TX details 5 Sign with HW wallet 6 Signed TX → back 7–8 Post-verify → broadcast

The air-gap relay

The relay is a dedicated single-board device that acts as a one-way bridge. It runs a minimal service that accepts TX plans from the agent host and makes them available to the signing device through a shared buffer file.

The bridge carries only two types of data:

Even if the bridge is fully compromised, the attacker gets only raw TX bytes — no keys, no wallet state, no ability to modify calldata (post-sign verification catches any tampering).
What if the bridge fails mid-signing? The unsigned TX stays in the relay buffer. No partial state is possible — either a complete signed TX returns, or nothing does. Retry when the bridge recovers.

Device isolation handles the signing threat. For runtime threats on the networked machine itself, the Security page covers the sandbox architecture, network monitoring, and approval hygiene rules.

Zypher Hardware

Don't trust software. Trust physics.
Zypher is an air-gapped EVM signer that uses optocouplers (6N137) for physically one-directional data flow. Light goes one direction through the diode. No firmware exploit can reverse a photon. Open-source. Auditable from silicon to firmware.

The relay bridge described above works. But it relies on software isolation — firewalls, file permissions, network configuration. Zypher replaces software assumptions with physics: three optocouplers enforce data direction at the hardware level. Two MCUs (RP2040) run ~150 lines of C each. Two IPS displays (3.5", 320×480) show every transaction in human-readable form. Auto-verification compares signed calldata with the original — byte by byte, on-device.

ZYPHER BOX AGENT HOST networked SIGNER air-gapped OPTO #1 6N137 → TX in MCU #1 RP2040 · INPUT ASCII filter parse & display store calldata USB HID keyboard DISPLAY #1 3.5" IPS · original TX OPTO #3 cross-verify ↓ calldata copy MCU #2 RP2040 · OUTPUT ASCII filter AUTO-VERIFY match / mismatch USB CDC serial signed TX OPTO #2 ← 6N137 signed TX out DISPLAY #2 3.5" IPS · VERIFY result Input path Output path Cross-verify

Three optocouplers, three directions

Optocoupler Direction Purpose
#1 (6N137) Agent Host → MCU #1 Unsigned TX enters the box
#2 (6N137) MCU #2 → Agent Host Verified signed TX exits the box
#3 (6N137) MCU #1 → MCU #2 Original calldata for auto-verification

All three are LED → photodiode. Light goes one direction. The reverse pin is physically disconnected — no wire, not just no software. This is not a firewall rule. It's a property of the component.

The firmware: ~150 lines of auditable code

Each MCU runs embassy-rs on the RP2040. The core security boundary is a single function — an ASCII filter that drops everything except printable characters. Private keys (binary data) physically cannot pass through. Escape sequences, control characters, binary payloads — all dropped.

// Zypher MCU firmware — core filter (RP2040, embassy-rs)
// Only printable ASCII passes. Everything else is dropped.
// Private keys are binary data — they cannot survive this filter.

/// Filter a single byte through the ASCII gate.
/// Printable range (0x20..0x7E) and newline pass.
/// Everything else — control chars, binary, escape sequences — is dropped.
fn filter_byte(b: u8) -> Option<u8> {
    match b {
        0x20..=0x7E | b'\n' => Some(b),
        _ => None,
    }
}

/// Process a UART buffer: filter each byte, collect survivors.
/// Any non-ASCII byte is silently discarded — no error, no retry, no log.
/// This means binary key material (typically 0x00-0x1F, 0x80-0xFF)
/// is physically destroyed at the boundary.
fn filter_buffer(input: &[u8]) -> Vec<u8> {
    input.iter().filter_map(|&b| filter_byte(b)).collect()
}

/// Auto-verify: compare calldata from signed TX with the original
/// received from MCU #1 via optocoupler #3.
/// Returns MATCH (green screen) or MISMATCH (red screen, block send).
fn verify_calldata(original: &[u8], signed_tx_calldata: &[u8]) -> bool {
    if original.len() != signed_tx_calldata.len() {
        return false;
    }
    original.iter().zip(signed_tx_calldata).all(|(a, b)| a == b)
}
Why this matters: Even if the signing device is fully compromised and tries to exfiltrate keys through the output channel, MCU #2's ASCII filter drops all binary data. And you'd see the exfiltration attempt on Display #2 — because it's not a signed transaction.

What Zypher defends against

Key extraction
Binary key data is dropped by ASCII filter. Hex-encoded key would be visible on Display #2 and clearly not a signed TX.
TX substitution
MCU #2 auto-verifies calldata byte-for-byte against the original from MCU #1 (via optocoupler #3). Mismatch = red screen, send blocked.
Blind signing
Two 3.5" IPS displays show decoded TX details. Display #1: original. Display #2: what was actually signed + verification status.
Firmware exploit
~150 lines of C per MCU. No complex parsers, no variable-length buffers, no WiFi/BT/radio in silicon. Fully auditable.

Comparison with existing solutions

Solution Weakness
Ledger / Trezor Bidirectional USB, closed firmware, blind signing common
Safe Multisig All signers see same UI — Lazarus showed fake TX to all ($1.5B Bybit)
Keystone (QR) QR parser = attack surface for malformed payloads
Hot wallets Keys in browser memory = on the internet
Zypher Three physical diodes, ASCII filter, auto-verify, two displays. Only physics.

Bill of materials

RP2040 MCUs
6N137 Optocouplers
3.5" IPS Displays
~150
Lines of firmware

Open-source from silicon to firmware. EVM-compatible — any chain, any contract, any calldata. Uses cast (Foundry) for signing with full calldata control.