JC3 Documentation
Everything you need to deploy, configure, and operate the JC3 tactical mesh networking platform.
01 Quick Start
Get a JC3 mesh network running in under 5 minutes. This guide walks
through the minimal steps to establish encrypted communications
between two or more devices using the jc3d daemon,
the JC3 COP web dashboard, and the JC3 LINK Android app.
-
Step 1: Download the jc3d binary
Download the JC3 daemon for your platform from the Downloads page. The daemon is a single static binary with zero runtime dependencies. Available for Linux x86_64 (~11 MB), Linux ARM64 (~10 MB), and Windows x64 (~11 MB).
bash# Linux x86_64 wget https://jcan.us/downloads/jc3d-linux-amd64 chmod +x jc3d-linux-amd64 sudo mv jc3d-linux-amd64 /usr/local/bin/jc3d # Windows — download jc3d-windows-amd64.exe and place on PATH -
Step 2: Run jc3d
Launch the daemon. On first run, jc3d automatically generates a TLS certificate pair (ECDSA P-384) and a 256-bit API bearer token. All generated credentials are stored in
~/.jc3/on Linux or%USERPROFILE%\.jc3\on Windows.bash# Start the daemon jc3d # Expected output on first run: # [INFO] Generated TLS cert: ~/.jc3/tls-cert.pem # [INFO] Generated TLS key: ~/.jc3/tls-key.pem # [INFO] Generated API token: ~/.jc3/api-token # [INFO] Listening on https://127.0.0.1:9443 # [INFO] mDNS discovery active on all interfaces -
Step 3: Open the COP dashboard
Navigate to
https://127.0.0.1:9443in your browser. The JC3 COP dashboard loads directly from the daemon. Because jc3d uses a self-signed TLS certificate, your browser will show a certificate warning on the first visit. Accept the certificate to proceed. You will see your local node on the map and any discovered peers. -
Step 4: Note your API token
Retrieve the bearer token generated during first run. This token is required for all API calls and for connecting the Android app.
bashcat ~/.jc3/api-token # Output: eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9... -
Step 5: Connect JC3 LINK on Android
Install the JC3 LINK APK on your Android device (API 26+ / Android 8.0 or later). Open Settings within the app and enter the daemon IP address and API token from Step 4. The app supports both local (WiFi LAN) and remote (relay) connections.
-
Step 6: Add more devices
Run
jc3don a second machine connected to the same WiFi network. Peers auto-discover each other via WiFi mDNS within seconds. No manual IP configuration is needed. Each daemon generates its own TLS identity and joins the mesh automatically.bash# On the second machine jc3d # [INFO] Discovered peer: 192.168.1.42 (ALPHA-1) # [INFO] TLS handshake complete — dual-layer encryption active
curl -sk https://127.0.0.1:9443/api/v1/peers -H "Authorization: Bearer YOUR_TOKEN"
02 System Requirements
The following table lists the minimum and recommended hardware for each JC3 component. The daemon and relay are compiled with Go 1.22 as static binaries, requiring no external runtime or shared libraries. The desktop app is built on Electron 29 with Node 20 LTS. The Android apps target SDK 34 (Android 14) with a minimum of API 26 (Android 8.0) and are built with JDK 17.
| Component | Minimum | Recommended |
|---|---|---|
| jc3d (daemon) | 1 CPU core, 512 MB RAM, 100 MB disk | 2+ CPU cores, 2 GB RAM, Go 1.22 static binary |
| JC3 COP (web) | Chrome 90+, Firefox 88+, Edge 90+ | Chromium-based browser, WebGL 2.0 GPU |
| JC3 COP Desktop | Windows 10+ or Linux (AppImage), 4 GB RAM | 8 GB RAM, dedicated GPU, 1280x720+ display |
| JC3 LINK (Android) | Android 8.0+ (API 26), 64 MB free storage | Android 12+, biometric sensor, GPS |
| jc3-relay (server) | Linux VPS, 1 CPU core, 512 MB RAM | Ubuntu 22.04+, 2+ CPU, 1 GB RAM, SSD |
jc3d and
jc3-relay ship as native ARM64 binaries for deployment
on Raspberry Pi 4/5, NVIDIA Jetson, and other embedded platforms.
03 Network Requirements
JC3 is designed to work with zero infrastructure. No internet connection, cell service, or servers are required for basic mesh operation. The daemon creates its own encrypted overlay network and discovers peers automatically.
Transport Types
| Transport | Range | Bandwidth | License Tier |
|---|---|---|---|
| WiFi LAN | ~100m (line of sight) | High (50+ Mbps) | Community |
| Bluetooth Classic | ~30m | Medium (2 Mbps) | Professional |
| WiFi Direct | ~200m | High (50+ Mbps) | Professional |
| BLE (Bluetooth Low Energy) | ~50m | Low (125 Kbps) | Professional |
| Cellular / LTE | Unlimited* | Variable | Professional |
| SDR (Software Defined Radio) | Variable | Low-Medium | Professional |
* Cellular transport routes through a JC3 RELAY server. All traffic remains encrypted end-to-end regardless of transport layer.
Firewall and Port Requirements
For environments with managed firewalls, the following ports must be open between mesh nodes and the relay:
| Port | Protocol | Purpose |
|---|---|---|
| 9443 | TCP (HTTPS) | Daemon REST API and COP dashboard |
| 9000 | TCP | Mesh relay traffic (node-to-relay) |
| 5353 | UDP (mDNS) | Local peer discovery (LAN only) |
| 51820 | UDP | WireGuard VPN tunnel (optional) |
04 JC3 MESH (Android)
JC3 MESH is the core mesh networking application for Android. It turns any Android device into an encrypted mesh node capable of multi-hop routing, position sharing, and end-to-end encrypted messaging. The app targets Android SDK 34 with a minimum API level of 26 and is built with JDK 17.
Installation
-
Download the APK
Get
chaz-mesh-v2.0.2.apkfrom the Downloads page. Enable "Install from unknown sources" in your device settings under Settings > Security or Settings > Apps > Special Access. - Install and launch Tap the downloaded APK to install. Open JC3 MESH and grant the requested permissions: Location (required by Android for WiFi scanning), Nearby Devices, WiFi, and Bluetooth.
- Set your callsign Enter a callsign (e.g., ALPHA-1) and an optional unit/team identifier. This callsign is your identity on the mesh and appears to all peers.
- Join or create a network Enter a network passphrase to join an existing mesh, or create a new network. The passphrase derives the network-wide ChaCha20-Poly1305 encryption key. Tap "Start Mesh" to begin peer discovery. Nearby JC3 devices appear automatically, and all communications are encrypted from the first packet.
05 JC3 COP (Web/Desktop)
JC3 COP provides a real-time Common Operating Picture with 2D
(Leaflet) and 3D (CesiumJS) map views, encrypted messaging,
SIP-based voice calls, incident management, geofencing, and
network health monitoring. The COP dashboard is served directly
by the jc3d daemon at https://127.0.0.1:9443.
Web App
Open a browser and navigate to the daemon's web interface at
https://127.0.0.1:9443. The COP dashboard loads
automatically with no separate installation. Accept the
self-signed certificate warning on first visit.
Desktop App (Electron 29)
- Download the installer Get the Electron app from Downloads — available as a Windows installer (.exe, ~80 MB), a Windows portable executable (~72 MB), or a Linux AppImage.
-
Connect to daemon
On first launch, enter the daemon address and API token. For
local operation, use
https://127.0.0.1:9443. For remote operation, use the relay server address. - Explore the dashboard The desktop COP includes all web COP features plus a built-in process watchdog for automatic daemon restart, system tray integration, and DPAPI-encrypted credential storage.
Key Features
- Real-time node tracking with MGRS grid overlay and position history
- Incident management with geofencing, alerting, and CSV export
- Network health monitoring and topology visualization
- Integrated chat with TAK GeoChat and SIGMA XMPP bridging
- SIP-based voice calls over the mesh (SRTP encrypted)
- AI-powered analytics drawer with 8 quick action commands
- GeoJSON import/export, light theme toggle, keyboard shortcuts
- Offline-capable with local tile caching
06 JC3 RELAY (Server)
JC3 RELAY bridges mesh networks across the internet, provides the REST API and WebSocket feeds for remote COP clients, and hosts optional TAK, SIGMA, and SIP bridges. The relay is a single static Go binary with no runtime dependencies.
Deployment
# Download the relay binary
wget https://jcan.us/downloads/jc3-relay-linux-amd64
chmod +x jc3-relay-linux-amd64
sudo mv jc3-relay-linux-amd64 /usr/local/bin/jc3-relay
# Create config directory
sudo mkdir -p /opt/jc3
sudo nano /opt/jc3/config.yaml
# Start the relay
jc3-relay --config /opt/jc3/config.yaml
# Or install as a systemd service
sudo cp jc3-relay.service /etc/systemd/system/
sudo systemctl enable --now jc3-relay
Configuration
Key settings in /opt/jc3/config.yaml:
listen_port— TCP port for mesh node connections (default: 9000)https_port— HTTPS port for REST API and COP (default: 9443)auth_password— Relay authentication password (min 12 chars)tls_cert/tls_key— TLS certificate pathsbridges— Enable TAK, SIGMA, or SIP bridgesai_engine— Enable AI-powered analytics (requires API key)
07 JC3 LINK (Android)
JC3 LINK is the simplified communications app for non-technical users. It provides one-button push-to-talk voice, text messaging, and position sharing with automatic mesh connectivity. JC3 LINK uses the same dual-layer encryption as JC3 MESH but presents a streamlined interface focused on rapid communications.
Setup
-
Install the APK
Download and install
jc3-link-0.1.0-debug.apkfrom Downloads. Requires Android 8.0+ (API 26) with 64 MB free storage. -
Configure connection
Open Settings in the app. Enter the daemon IP address (e.g.,
192.168.1.42) and paste the API token from~/.jc3/api-tokenon the daemon host. - Communicate Tap the microphone button for push-to-talk voice. Use the text field for messaging. JC3 LINK automatically discovers peers and encrypts all traffic via the connected daemon.
08 API Overview
The JC3 daemon exposes a RESTful HTTPS API and a WebSocket interface for real-time event streaming. All API endpoints are served over TLS on port 9443 and require Bearer token authentication. The API follows REST conventions with JSON request and response bodies.
Base URL
https://127.0.0.1:9443/api/v1
Authentication
All API requests must include a Bearer token in the
Authorization header. The token is generated
automatically when jc3d starts for the first time and is stored
in ~/.jc3/api-token.
Authorization: Bearer <your-api-token>
Requests without a valid token receive a 401 Unauthorized
response. Tokens do not expire but can be rotated by deleting
~/.jc3/api-token and restarting jc3d.
Response Format
All successful responses return JSON with a consistent envelope:
{
"status": "ok",
"data": { ... },
"timestamp": "2026-03-21T14:30:00Z"
}
Error responses use standard HTTP status codes (400, 401, 403,
404, 500) with a JSON body containing "status": "error"
and a "message" field describing the issue. Error
messages are intentionally generic to prevent information leakage.
Rate Limiting
The API enforces a rate limit of 500 requests per 60-second
window per source IP. This accommodates NATed mesh nodes sharing
a single egress IP. Exceeding the limit returns
429 Too Many Requests.
09 REST Endpoints
The following table lists the 20 primary REST endpoints. All
paths are relative to the base URL
https://127.0.0.1:9443/api/v1.
| Method | Endpoint | Description |
|---|---|---|
GET |
/status |
Node status, uptime, version, peer count, transport states |
GET |
/peers |
List all discovered peers with callsign, position, signal, transport |
POST |
/message |
Send encrypted text message to a peer or broadcast channel |
GET |
/incidents |
List all incidents (filterable by status, severity, date) |
POST |
/incidents |
Create a new incident with title, description, lat/lng, severity |
GET |
/tasks |
List all tasks (filterable by assignee, status, priority) |
POST |
/tasks |
Create a new task with title, assignee, priority, due date |
GET |
/geofences |
List all geofence zones with type, coordinates, and alert rules |
POST |
/geofences |
Create a geofence (circle or polygon) with enter/exit alerts |
POST |
/voice/call |
Initiate an encrypted SIP voice call to a peer or group |
GET |
/sip/cdr |
Call detail records: caller, callee, duration, codec, quality |
POST |
/ai/query |
Submit a natural-language query to the AI analytics engine |
GET |
/firewall/rules |
List mesh firewall rules (allow/deny by peer, port, protocol) |
GET |
/vpn/peers |
List WireGuard VPN peers with handshake time and transferred bytes |
GET |
/license/status |
Current license tier, expiration, node count, feature flags |
GET |
/messages |
Retrieve message history (paginated, filterable by peer/channel) |
GET |
/network/topology |
Current mesh topology graph: nodes, links, routes, hop counts |
GET |
/network/health |
Network health metrics: latency, packet loss, throughput per link |
POST |
/position |
Update this node's GPS position (lat, lon, alt, accuracy) |
DELETE |
/voice/call |
End the active voice call |
10 WebSocket Events
Connect to wss://127.0.0.1:9443/ws?token=YOUR_TOKEN
for real-time event streaming. The WebSocket connection requires
authentication via query parameter or by sending an auth frame
immediately after connection. Events are JSON-encoded.
| Event | Direction | Description |
|---|---|---|
message_received |
Server → Client | New encrypted message received from the mesh |
peer_update |
Server → Client | Peer status change (join, leave, position update, signal change) |
call_incoming |
Server → Client | Incoming voice call notification with caller ID and codec |
call_ended |
Server → Client | Voice call terminated (includes duration and quality stats) |
incident_update |
Server → Client | Incident created, updated, or closed |
geofence_alert |
Server → Client | Node entered or exited a geofence zone |
network_change |
Server → Client | Topology change: new link, lost link, route recalculation |
alert |
Server → Client | Security alert: firewall violation, anomaly, trust score change |
transport_failover |
Server → Client | Transport switched (e.g., WiFi to Bluetooth fallback) |
send_message |
Client → Server | Send a message via WebSocket (alternative to REST POST) |
subscribe |
Client → Server | Subscribe to specific event channels for filtered delivery |
11 API Examples
All examples below use curl with the -k
flag to accept self-signed TLS certificates. Replace
YOUR_TOKEN with the contents of
~/.jc3/api-token. Responses are piped through
jq for readability.
Get Mesh Status
curl -sk https://127.0.0.1:9443/api/v1/status \
-H "Authorization: Bearer YOUR_TOKEN" | jq .
{
"status": "ok",
"data": {
"callsign": "ALPHA-1",
"version": "2.0.0",
"uptime_seconds": 86420,
"peers_count": 7,
"transports": {
"wifi": "active",
"bluetooth": "active",
"relay": "connected"
},
"encryption": "dual-layer",
"license_tier": "professional"
}
}
List Peers
curl -sk https://127.0.0.1:9443/api/v1/peers \
-H "Authorization: Bearer YOUR_TOKEN" | jq .
{
"status": "ok",
"data": [
{
"callsign": "BRAVO-1",
"node_id": "a3f8c1d2",
"transport": "wifi",
"signal_dbm": -42,
"lat": 38.8977,
"lon": -77.0365,
"last_seen": "2026-03-21T14:29:55Z",
"hops": 1
},
{
"callsign": "CHARLIE-2",
"node_id": "b7e4a9f1",
"transport": "bluetooth",
"signal_dbm": -58,
"lat": 38.8979,
"lon": -77.0362,
"last_seen": "2026-03-21T14:29:50Z",
"hops": 2
}
]
}
Send a Message
curl -sk -X POST https://127.0.0.1:9443/api/v1/message \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"to": "BRAVO-1",
"text": "Rally point ECHO, 0630Z.",
"priority": "routine"
}' | jq .
{
"status": "ok",
"data": {
"message_id": "msg-4f2a8c91",
"delivered": true,
"hops": 1,
"latency_ms": 12
}
}
Create an Incident
curl -sk -X POST https://127.0.0.1:9443/api/v1/incidents \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Suspicious activity at checkpoint DELTA",
"description": "Unknown vehicle observed at 0615Z, moving north.",
"severity": "high",
"lat": 38.8977,
"lng": -77.0365
}' | jq .
List Incidents
curl -sk https://127.0.0.1:9443/api/v1/incidents \
-H "Authorization: Bearer YOUR_TOKEN" | jq .
Create a Task
curl -sk -X POST https://127.0.0.1:9443/api/v1/tasks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Establish OP at grid 18SUJ2337406727",
"assignee": "BRAVO-1",
"priority": "high",
"due": "2026-03-21T18:00:00Z"
}' | jq .
Create a Geofence
curl -sk -X POST https://127.0.0.1:9443/api/v1/geofences \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "AO-NORTH",
"type": "circle",
"lat": 38.9000,
"lng": -77.0400,
"radius_m": 500,
"alert_on_enter": true,
"alert_on_exit": true
}' | jq .
Initiate Voice Call
curl -sk -X POST https://127.0.0.1:9443/api/v1/voice/call \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"target": "BRAVO-1", "mode": "direct"}' | jq .
Get Call Detail Records
curl -sk https://127.0.0.1:9443/api/v1/sip/cdr \
-H "Authorization: Bearer YOUR_TOKEN" | jq .
AI Query
curl -sk -X POST https://127.0.0.1:9443/api/v1/ai/query \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "What are the current network anomalies?"
}' | jq .
Get Firewall Rules
curl -sk https://127.0.0.1:9443/api/v1/firewall/rules \
-H "Authorization: Bearer YOUR_TOKEN" | jq .
List VPN Peers
curl -sk https://127.0.0.1:9443/api/v1/vpn/peers \
-H "Authorization: Bearer YOUR_TOKEN" | jq .
{
"status": "ok",
"data": [
{
"public_key": "aB3xK...truncated",
"allowed_ips": "10.13.37.2/32",
"last_handshake": "2026-03-21T14:28:00Z",
"tx_bytes": 1048576,
"rx_bytes": 524288
}
]
}
Get License Status
curl -sk https://127.0.0.1:9443/api/v1/license/status \
-H "Authorization: Bearer YOUR_TOKEN" | jq .
{
"status": "ok",
"data": {
"tier": "professional",
"expires": "2027-03-21T00:00:00Z",
"max_nodes": 50,
"features": ["bluetooth", "wifi_direct", "vpn", "ai", "tak_bridge"]
}
}
WebSocket Connection
var ws = new WebSocket('wss://127.0.0.1:9443/ws?token=YOUR_TOKEN');
ws.onopen = function() {
// Subscribe to specific event channels
ws.send(JSON.stringify({
type: 'subscribe',
channels: ['messages', 'peers', 'alerts', 'incidents']
}));
};
ws.onmessage = function(event) {
var data = JSON.parse(event.data);
console.log('Event:', data.type, data);
// Handle specific event types
if (data.type === 'peer_update') {
console.log('Peer:', data.callsign, data.transport, data.signal_dbm);
}
if (data.type === 'geofence_alert') {
console.log('Geofence:', data.zone, data.action, data.node);
}
};
12 Single Node Deployment
The simplest deployment: one laptop or workstation running jc3d. The daemon serves the COP dashboard, handles peer discovery, and provides the full REST API. This configuration is suitable for individual operators, field assessment, or development testing.
# Download and install
wget https://jcan.us/downloads/jc3d-linux-amd64
chmod +x jc3d-linux-amd64
sudo mv jc3d-linux-amd64 /usr/local/bin/jc3d
# Run the daemon (generates TLS certs + API token on first run)
jc3d
# Open the COP dashboard
# Navigate to https://127.0.0.1:9443 in your browser
# Verify the API is operational
curl -sk https://127.0.0.1:9443/api/v1/status \
-H "Authorization: Bearer $(cat ~/.jc3/api-token)" | jq .
The daemon immediately begins mDNS-based peer discovery on all available network interfaces. Other JC3 nodes on the same LAN segment are discovered automatically within seconds. No manual peer configuration is required.
13 Multi-Node Mesh
For three or more devices on the same WiFi network, JC3 automatically builds a full mesh topology with multi-hop routing. No additional configuration is needed beyond the single node setup described above.
How It Works
Each node discovers its neighbors via mDNS and establishes encrypted links. The daemon builds a routing table using a distance-vector protocol. Messages are forwarded hop-by-hop until they reach the destination. If a link fails (e.g., a device moves out of WiFi range), traffic is automatically rerouted through alternate paths with sub-second convergence.
Example: 5-Node Field Deployment
# Device 1 (Command Post)
jc3d
# Device 2 (OP North) — auto-discovers Device 1
jc3d
# Device 3 (OP South) — auto-discovers Devices 1 & 2
jc3d
# Devices 4 & 5 (Android) — install JC3 LINK, enter daemon IP
# All 5 nodes form a self-healing mesh
Multi-Transport
Nodes can use multiple transports simultaneously. A node might connect to one peer via WiFi LAN and another via Bluetooth. The daemon handles transport selection, link quality monitoring, and automatic failover. If WiFi drops, traffic seamlessly transitions to Bluetooth or WiFi Direct without operator intervention.
14 Cloud Relay Deployment
Deploy JC3 RELAY on a Linux VPS (AWS, Azure, DigitalOcean, etc.) to bridge geographically separated mesh networks. The relay accepts connections from remote jc3d nodes over the internet and routes traffic between them while maintaining end-to-end encryption. The relay binary is a single static Go executable with no dependencies.
# On your cloud server (Ubuntu 22.04+ recommended)
# 1. Download the relay binary
wget https://jcan.us/downloads/jc3-relay-linux-amd64
chmod +x jc3-relay-linux-amd64
sudo mv jc3-relay-linux-amd64 /usr/local/bin/jc3-relay
# 2. Generate TLS certificate (or use Let's Encrypt)
sudo apt install -y certbot
sudo certbot certonly --standalone -d relay.yourdomain.com
# 3. Create configuration
sudo mkdir -p /opt/jc3
cat <<EOF | sudo tee /opt/jc3/config.yaml
listen_port: 9000
https_port: 9443
tls_cert: /etc/letsencrypt/live/relay.yourdomain.com/fullchain.pem
tls_key: /etc/letsencrypt/live/relay.yourdomain.com/privkey.pem
auth_password: "YourSecurePassword12chars+"
EOF
# 4. Create systemd service
cat <<EOF | sudo tee /etc/systemd/system/jc3-relay.service
[Unit]
Description=JC3 Relay Server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/jc3-relay --config /opt/jc3/config.yaml
Restart=always
RestartSec=5
ProtectSystem=strict
NoNewPrivileges=true
ReadWritePaths=/opt/jc3
[Install]
WantedBy=multi-user.target
EOF
# 5. Enable and start
sudo systemctl daemon-reload
sudo systemctl enable --now jc3-relay
Firewall Rules
Open the following ports on your VPS firewall (ufw, iptables, or cloud security group):
- TCP 9000 — Mesh relay traffic from field nodes (required)
- TCP 9443 — HTTPS REST API and COP dashboard (required)
- TCP 443 — HTTPS if using nginx reverse proxy (optional)
- UDP 51820 — WireGuard VPN tunnel (optional)
nginx Reverse Proxy (Optional)
For production deployments, place nginx in front of jc3-relay to handle TLS termination, add security headers (CSP, HSTS), and serve the COP dashboard on standard port 443.
15 VPN Gateway Setup
JC3 RELAY integrates with WireGuard to provide an encrypted VPN gateway for mesh nodes that cannot reach the relay directly. This is useful for nodes behind restrictive firewalls or on cellular connections.
# Install WireGuard on the relay server
sudo apt install -y wireguard
# Generate server keys
wg genkey | tee server_private.key | wg pubkey > server_public.key
# Configure WireGuard interface
cat <<EOF | sudo tee /etc/wireguard/wg0.conf
[Interface]
PrivateKey = $(cat server_private.key)
Address = 10.13.37.1/24
ListenPort = 51820
[Peer]
PublicKey = CLIENT_PUBLIC_KEY_HERE
AllowedIPs = 10.13.37.2/32
EOF
# Start WireGuard
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0
# jc3-relay auto-detects the WireGuard interface
# and routes mesh traffic through the tunnel
Enterprise Deployment (Future)
For large-scale enterprise deployments, JC3 supports deployment on Harvester HCI with Kubernetes orchestration. This architecture enables automatic scaling of relay instances, centralized certificate management, and multi-site federation. Contact sales@jcan.us for details.
16 Encryption
JC3 implements dual-layer encryption aligned with the NSA Commercial Solutions for Classified (CSfC) architecture. Every packet on the mesh is encrypted twice using independent algorithms from different cryptographic families, ensuring that compromise of one layer does not expose the other.
Dual-Layer Architecture
| Layer | Algorithm | Key Size | Purpose |
|---|---|---|---|
| Inner Layer (per-peer) | AES-256-GCM | 256-bit | Primary encryption, unique key per peer pair |
| Outer Layer (network-wide) | ChaCha20-Poly1305 | 256-bit | Secondary encryption, derived from network passphrase |
| Key Exchange | X25519 (ECDH) | 256-bit | Per-session key agreement between peers |
| Post-Quantum (Enterprise) | ML-KEM-768 + ML-DSA-65 | 768-bit / 65-bit | Hybrid post-quantum KEM and signatures (FIPS 203/204) |
Double Ratchet Forward Secrecy
Each peer-to-peer channel uses the Double Ratchet algorithm (based on the Signal Protocol design). Every message derives a unique per-message key. Forward secrecy is maintained: compromising a single message key does not expose past or future messages. Ratchet state advances with every send and receive operation, providing continuous key rotation without manual intervention.
Wire Protocol
The JC3 wire protocol uses a 64-byte header containing the encrypted payload length, nonce, and HMAC-SHA256 authentication tag. Every packet includes a monotonic nonce and timestamp for replay protection (300-second window). The replay protector maintains a sliding window of seen nonces to detect and reject duplicate or replayed packets.
FIPS 140-3 Path
The Go daemon is compiled with the BoringCrypto module, which
provides FIPS-validated cryptographic primitives. All
cryptographic operations (AES-GCM, SHA-256, ECDSA, ECDH) route
through the BoringCrypto boundary when the
GOEXPERIMENT=boringcrypto build flag is set.
17 PKI / CA System
JC3 includes a built-in X.509 Public Key Infrastructure for mutual TLS authentication between all nodes. The PKI ensures that only authorized devices can join the mesh.
Certificate Hierarchy
- Root CA — ECDSA P-384, self-signed, generated during initial setup. Can optionally be backed by a YubiKey HSM for hardware-protected key storage.
- Intermediate CA — Signs node certificates, can be rotated independently of the root.
- Node Certificates — ECDSA P-384, issued per device, stored in
~/.jc3/. Used for mutual TLS on every mesh connection.
Enrollment
New devices are enrolled via QR code scan or manual certificate exchange through the API. The enrollment workflow:
- New device generates an ECDSA P-384 key pair on first run
- Device presents its public key to the CA (via QR scan or REST API)
- CA validates the request and signs the node certificate
- Device stores the signed certificate in
~/.jc3/node-cert.pem - On every mesh connection, both peers present and verify certificates before exchanging traffic
Revocation
Compromised or lost devices can be revoked via the relay admin panel or the REST API. Revocation is propagated to all nodes in the mesh via CRL (Certificate Revocation List) distribution. Revoked nodes are immediately blocked from establishing new connections.
RBAC (Role-Based Access Control)
The relay enforces three authorization roles:
- admin — Full access to all API endpoints, user management, and system configuration
- operator — Read/write access to operational endpoints (messages, incidents, tasks, geofences) but no admin functions
- viewer — Read-only access to the COP dashboard and status endpoints
18 Compliance
JC3 is designed for deployment in classified and sensitive environments. The platform architecture addresses the following standards and frameworks:
| Standard | Status | Coverage |
|---|---|---|
| FIPS 140-3 | Compliance Path | BoringCrypto module, CAVP-validated algorithms (AES, SHA-2, ECDSA), automated self-test procedures |
| NIST SP 800-53 Rev. 5 | Implemented | Access Control (AC), Audit (AU), Identification/Authentication (IA), System Communications (SC), System Integrity (SI) |
| DISA STIGs | Aligned | Server hardening (systemd sandboxing, NoNewPrivileges), application security, network STIG controls |
| NSA CSfC | Architecture Aligned | Dual-layer encryption from independent algorithm families (AES-GCM inner, ChaCha20-Poly1305 outer) |
| FIPS 203/204 | Implemented (Enterprise) | ML-KEM-768 post-quantum key encapsulation, ML-DSA-65 post-quantum digital signatures |
| OWASP Top 10 | Mitigated | XSS (output escaping), injection (parameterized queries), broken auth (token + lockout), CSRF, SSRF |
| MITRE ATT&CK | Mapped | Detection and mitigation controls for relevant TTPs including lateral movement, C2, and data exfiltration |