intermediate clitestingintegrationdeveloper-tools

CLI Device Tool

Command-line testing device for Sigil Auth integration development

CLI Device Tool

sigil-device is a command-line tool that simulates an iOS or Android device for Sigil Auth integration testing. Use it to test authentication flows, verify server behavior, and automate CI smoke tests without requiring a physical mobile device.

When to use this: Integration testing, local development, CI/CD pipelines, server verification.
When to use the mobile app: End-user authentication, production workflows, hardware-backed key security.

The CLI device uses software-generated keys (mnemonic-derived ECDSA P-256) instead of hardware chips. Perfect for testing server logic, but not a replacement for the real mobile app’s Secure Enclave/StrongBox security in production.

What It Does

The CLI device acts as a virtual authenticator:

  • Generates hardware-backed key pairs (mnemonic-derived ECDSA P-256)
  • Pairs with Sigil Auth servers
  • Registers with push relay for WebSocket delivery
  • Listens for authentication challenges
  • Signs challenge responses
  • Supports multi-party authorization (MPA) flows
  • Decrypts ECIES-encrypted payloads

Perfect for integration testing, local development, and CI/CD pipelines.


Installation

One-Liner (Linux/macOS)

curl -fsSL https://raw.githubusercontent.com/sigilauth/cli-device/main/install.sh | sh

Package Managers

macOS (Homebrew):

brew tap sigilauth/tap
brew install sigil-device

Debian/Ubuntu (APT):

curl -fsSL https://repo.sigilauth.com/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/sigilauth.gpg
echo "deb [signed-by=/usr/share/keyrings/sigilauth.gpg] https://repo.sigilauth.com/apt stable main" | sudo tee /etc/apt/sources.list.d/sigilauth.list
sudo apt update && sudo apt install sigil-device

Fedora/RHEL (DNF):

sudo dnf config-manager --add-repo https://repo.sigilauth.com/rpm/sigilauth.repo
sudo dnf install sigil-device

Arch Linux (Pacman):

# Install from AUR
yay -S sigil-device

Alpine Linux (APK):

echo "@sigilauth https://repo.sigilauth.com/apk/edge/main" | sudo tee -a /etc/apk/repositories
wget -qO- https://repo.sigilauth.com/gpg.key | sudo apk add --allow-untrusted
sudo apk add sigil-device@sigilauth

Windows (Scoop):

scoop bucket add sigilauth https://github.com/sigilauth/scoop-bucket
scoop install sigil-device

Linux users: See Installing on Linux for comprehensive installation guide including troubleshooting, systemd service setup, ARM support, and uninstallation.

From Source (Go 1.23+)

go install github.com/sigilauth/cli-device/cmd/sigil-device@latest

Installs to $GOPATH/bin/sigil-device (typically ~/go/bin/). Ensure $GOPATH/bin is in your PATH.

Pre-Built Binaries

Download for macOS, Windows, and Linux from releases:

# Example: Linux amd64
curl -LO https://github.com/sigilauth/cli-device/releases/download/v0.1.0/sigil-device_0.1.0_linux_amd64.tar.gz
tar -xzf sigil-device_0.1.0_linux_amd64.tar.gz
sudo mv sigil-device /usr/local/bin/

Verify Installation

sigil-device --version
# Output: sigil-device v0.1.0

Quick Start

1. Initialize Device Identity

Generate a new device keypair and mnemonic:

sigil-device init

Output:

✓ Device initialized
Fingerprint: a1b2c3d4e5f6...
Pictogram: 🍎 🍌 ✈️ 🚗 🐕 (apple banana plane car dog)
Mnemonic saved to: ~/.sigil-device/mnemonic.txt

Security note: The mnemonic is your device’s root secret. Back it up securely. The private key is never stored — it’s derived from the mnemonic on demand.

2. Pair with Your Sigil Server

Connect to your Sigil Auth server:

sigil-device pair --server https://auth.example.com

Output:

✓ Paired with server: https://auth.example.com
Server fingerprint: f1e2d3c4b5a6...
Server pictogram: 🔑 🌍 ⚡ 🎯 🔥 (key world lightning target fire)

Verify this pictogram matches the server's displayed identity.

IMPORTANT: Always verify the server pictogram matches what the server displays. A mismatch indicates a potential man-in-the-middle attack.

3. Register with Push Relay

Register for WebSocket-based push notifications:

sigil-device register --relay https://relay.sigilauth.com

Output:

✓ Registered with relay: https://relay.sigilauth.com
Device fingerprint: a1b2c3d4e5f6...
Push platform: websocket

4. Listen for Challenges

Start the WebSocket listener to receive authentication requests:

sigil-device listen

Output:

Connecting to https://relay.sigilauth.com/ws...
✓ Connected and authenticated
Fingerprint: a1b2c3d4e5f6...
Listening for challenges... (Ctrl+C to stop)

When a challenge arrives:

[challenge_abc123] Received auth
Approve? (y/N): y
Challenge approved

Auto-approve mode (for CI/testing):

sigil-device listen --auto-approve

Command Reference

sigil-device init

Initialize a new device identity with a BIP39 mnemonic.

Flags:

  • --force, -f — Overwrite existing identity (DESTRUCTIVE)

Example:

sigil-device init
sigil-device init --force  # Reinitialize (deletes current identity)

State files:

  • ~/.sigil-device/state.json — Public key, fingerprint, pictogram, pairing info
  • ~/.sigil-device/mnemonic.txt — 24-word BIP39 mnemonic (KEEP SECURE)

sigil-device pair

Pair with a Sigil Auth server by fetching its public key and verifying the pictogram.

Flags:

  • --server <url>, -s <url> — Server URL (required)

Example:

sigil-device pair --server https://auth.example.com

What it does:

  1. Fetches /info endpoint from server
  2. Receives server’s public key + pictogram
  3. Verifies pictogram matches key fingerprint
  4. Saves server URL + public key to state

Mutual trust: After pairing, both device and server have each other’s public keys for signature verification.


sigil-device register

Register with a push relay for WebSocket delivery.

Flags:

  • --relay <url>, -r <url> — Relay URL (required)

Example:

sigil-device register --relay https://relay.sigilauth.com

Production relay: https://relay.sigilauth.com

What it does:

  1. POSTs device public key to /devices/register
  2. Specifies push_platform: websocket
  3. Saves relay URL to state for use by listen

sigil-device listen

Listen for incoming authentication challenges via WebSocket.

Flags:

  • --relay <url>, -r <url> — Override relay URL (optional, uses registered URL by default)
  • --auto-approve, -a — Automatically approve all challenges without prompting

Example:

sigil-device listen
sigil-device listen --auto-approve  # CI mode
sigil-device listen --relay https://relay.staging.sigilauth.com  # Override relay

Interactive mode:

  • Prompts for approval: Approve? (y/N):
  • User types y to approve, anything else to reject

Auto-approve mode:

  • Instantly approves all challenges
  • Use in CI, smoke tests, or local dev loops
  • Security: Only use with test servers

Ctrl+C to stop listening.


sigil-device respond

Status: Not yet implemented (v0.2.0)

Sign and respond to an authentication challenge.

Planned usage:

sigil-device respond --challenge-id <id>

What it will do:

  1. Load challenge from state or accept as JSON input
  2. Verify server signature on challenge
  3. Sign challenge with device key
  4. POST signed response to server
  5. Return success/failure

sigil-device mpa-respond

Status: Not yet implemented (v0.2.0)

Respond to a multi-party authorization (MPA) challenge.

Planned usage:

sigil-device mpa-respond --challenge-id <id> --approve

What it will do:

  1. Decrypt ECIES-encrypted MPA context
  2. Display action requiring approval (e.g., “Delete production database”)
  3. Sign approval or rejection
  4. POST signed MPA response to server

sigil-device decrypt

Status: Not yet implemented (v0.2.0)

Decrypt an ECIES-encrypted payload.

Planned usage:

sigil-device decrypt --ciphertext <hex>

What it will do:

  1. Decode hex-encoded ciphertext
  2. Use device private key for ECIES decryption
  3. Output plaintext (e.g., mnemonic delivery, MPA context)

sigil-device whoami

Status: Not yet implemented (v0.2.0)

Display current device identity and pairing status.

Planned usage:

sigil-device whoami

Example output:

Device Fingerprint: a1b2c3d4e5f6...
Pictogram: 🍎 🍌 ✈️ 🚗 🐕 (apple banana plane car dog)
Public Key: 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798

Paired Server: https://auth.example.com
Server Fingerprint: f1e2d3c4b5a6...

Registered Relay: https://relay.sigilauth.com

Created: 2026-04-26T10:15:30Z

sigil-device unpair

Status: Not yet implemented (v0.2.0)

Remove device identity and all pairing data.

Planned usage:

sigil-device unpair
sigil-device unpair --force  # Skip confirmation

What it will do:

  1. Prompt for confirmation (unless --force)
  2. Delete ~/.sigil-device/state.json
  3. Delete ~/.sigil-device/mnemonic.txt
  4. Optionally notify server of unpair

DESTRUCTIVE: Cannot be undone. Back up mnemonic before unpair if recovery needed.


Common Workflows

First-Time Setup

# 1. Initialize device
sigil-device init

# 2. Pair with your server
sigil-device pair --server https://auth.example.com

# 3. Register for push notifications
sigil-device register --relay https://relay.sigilauth.com

# 4. Start listening
sigil-device listen

Testing Authentication Flow

# Terminal 1: Start listener
sigil-device listen --auto-approve

# Terminal 2: Trigger auth from your application
curl -X POST https://auth.example.com/challenge \
  -H 'Content-Type: application/json' \
  -d '{"user_id": "test_user", "action": "Sign in to dashboard"}'

# Terminal 1 output:
# [challenge_xyz] Received auth
# Challenge approved (auto-approve mode)

CI Smoke Test

Quick health check pattern:

# Verify device initialized and responsive (30s timeout)
sigil-device whoami && sigil-device listen --auto-approve --timeout=30s

Full CI workflow:

# .github/workflows/smoke-test.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Install sigil-device
        run: |
          curl -fsSL https://raw.githubusercontent.com/sigilauth/cli-device/main/install.sh | sh
      
      - name: Initialize test device
        run: sigil-device init
      
      - name: Health check
        run: sigil-device whoami
      
      - name: Pair with staging server
        run: sigil-device pair --server https://auth.staging.example.com
      
      - name: Register with relay
        run: sigil-device register --relay https://relay.staging.sigilauth.com
      
      - name: Start listener with timeout
        run: sigil-device listen --auto-approve --timeout=30s &
        timeout-minutes: 1
      
      - name: Trigger authentication
        run: |
          curl -f https://auth.staging.example.com/challenge \
            -H 'Content-Type: application/json' \
            -d '{"user_id":"ci_test","action":"CI smoke test"}'
      
      - name: Verify challenge processed
        run: echo "✓ Authentication flow verified"

MPA Flow Testing

Status: Requires mpa-respond command (not yet implemented)

# Planned workflow (v0.2.0):
sigil-device listen

# When MPA challenge arrives:
# [challenge_mpa_abc] Received mpa
# Action: Delete production database (db-prod-01)
# Requires: 2 of 3 approvals
# Approve? (y/N): y

State Management

All device state is stored in ~/.sigil-device/:

File Purpose Sensitive?
state.json Public key, fingerprint, pairing info No (public data)
mnemonic.txt 24-word BIP39 mnemonic YES — root secret

Security:

  • Private key is NEVER stored on disk
  • Private key derived from mnemonic on-demand for signing operations
  • Mnemonic is the single root secret — secure it like a password
  • State directory permissions: 700 (owner read/write/execute only)

Backup:

# Backup mnemonic (KEEP SECURE)
cp ~/.sigil-device/mnemonic.txt ~/Backups/sigil-mnemonic-$(date +%Y%m%d).txt

# Restore device on new machine
mkdir -p ~/.sigil-device
cp ~/Backups/sigil-mnemonic-20260426.txt ~/.sigil-device/mnemonic.txt
sigil-device init --force  # Regenerates state from mnemonic

Troubleshooting

“device not initialized”

# Run init first
sigil-device init

“not registered with relay”

# Register with relay before listening
sigil-device register --relay https://relay.sigilauth.com

“failed to connect to server”

Check:

  1. Server URL is correct (including http:// or https://)
  2. Server is running and accessible
  3. /info endpoint returns valid JSON
  4. Firewall allows outbound HTTPS

“server pictogram mismatch”

CRITICAL: This indicates a potential MITM attack. Do not proceed.

Verify:

  1. Server URL is correct (no typos)
  2. Server certificate is valid (check for HTTPS warnings)
  3. Network is trusted (avoid public WiFi)

WebSocket connection drops

  • Relay may have restarted — reconnect with sigil-device listen
  • Check network stability
  • Verify relay URL is correct


Version History

v0.1.0 (2026-04-26)

Implemented:

  • init — Device identity generation
  • pair — Server pairing with pictogram verification
  • register — Push relay registration
  • listen — WebSocket challenge listener (interactive + auto-approve)

Planned for v0.2.0:

  • respond — Challenge signing and submission
  • mpa-respond — MPA challenge handling
  • decrypt — ECIES payload decryption
  • whoami — Identity display
  • unpair — Device removal

Contributing

Contributions welcome! See CONTRIBUTING.md.

Development:

git clone https://github.com/sigilauth/cli-device.git
cd cli-device
go test ./...
go build -o sigil-device ./cmd/sigil-device

License: AGPL-3.0 (open source, copyleft)