plc-touch#
Please Touch. Secure enclave based keys for ATProto PLC rotation keys.
Named after the Please Touch Museum
A Rust TUI for managing AT Protocol (Bluesky) did:plc rotation keys with macOS Secure Enclave and Touch ID.
Take sovereign control of your DID PLC identity by generating hardware-backed P-256 keys and using them to directly sign and submit PLC operations — without needing your PDS to sign on your behalf.
Features#
- Key Management — Generate P-256 keys in the Secure Enclave (device-only, hardware-backed) or as software keys (synced via iCloud Keychain across Apple devices)
- Touch ID Signing — Every PLC operation signing triggers biometric authentication
- DID Inspection — View your DID document, rotation keys, verification methods, and services
- PLC Operations — Add/remove rotation keys, with diff preview before signing
- Audit Log — Browse the full PLC operation history for any DID
- PDS Login — Authenticate with your PDS for operations that require it (initial key addition via email token flow)
- Test Posts — Send posts to Bluesky from the TUI
Screenshots#
┌─plc-touch──did:plc:abc...xyz──🔑 mykey ● PDS─┐
│ 1 Keys │ 2 Identity │ 3 Sign │ 4 Audit │ ...│
├───────────────────────────────────────────────┤
│ ┌ Secure Enclave Keys ───────────────────────┐│
│ │ ▸ mykey * ││
│ │ did:key:zDnae... ││
│ │ iCloud Keychain (synced) Touch ID ││
│ └────────────────────────────────────────────┘│
│ q quit ? help 1-6 tabs n new d del s set │
└───────────────────────────────────────────────┘
Requirements#
- macOS 13+ (Ventura or later)
- Rust toolchain
- Apple Developer account (for Secure Enclave entitlements)
- Provisioning profile with
keychain-access-groupsentitlement
Setup#
- Clone and configure:
git clone https://github.com/yourusername/plc-touch.git
cd plc-touch
cp .env.example .env
- Edit
.envwith your Apple Developer signing details:
CODESIGN_IDENTITY="Apple Development: Your Name (XXXXXXXXXX)"
BUNDLE_ID="com.yourcompany.plc-touch"
TEAM_ID="XXXXXXXXXX"
-
Create a provisioning profile on developer.apple.com:
- Register your Mac's Provisioning UDID (find it in System Settings > General > About, or
system_profiler SPHardwareDataType | grep "Provisioning UDID") - Create a macOS App ID with your bundle ID
- Create a macOS Development provisioning profile
- Download and save as
embedded.provisionprofilein the project root
- Register your Mac's Provisioning UDID (find it in System Settings > General > About, or
-
Build and sign:
./build.sh
- Run:
target/release/plc-touch.app/Contents/MacOS/plc-touch
Usage#
Tabs#
| Tab | Key | Description |
|---|---|---|
| Keys | 1 |
Manage Secure Enclave / iCloud Keychain keys |
| Identity | 2 |
Inspect DID document, rotation keys, verification methods |
| Sign | 3 |
Review and sign staged PLC operations |
| Audit | 4 |
Browse PLC operation audit log |
| Post | 5 |
Send a test post to Bluesky |
| Login | 6 |
Authenticate with your PDS |
Key Bindings#
Global:
1-6— Switch tabs?— Helpq— Quit
Keys tab:
n— Generate new key (choose syncable or device-only)d— Delete selected keys— Set as active signing keyEnter— Copydid:keyto clipboard
Identity tab:
e— Enter/change DIDr— Refresh from PLC directorya— Add active key to rotation keysx— Remove selected rotation keym— Move rotation key (change priority)
Sign tab:
s— Sign operation with Touch IDj— Toggle JSON view
Audit tab:
j/Enter— Expand/collapse entry
Key Types#
When generating a key (n), you can toggle sync with Tab:
- Syncable
[Y]— Software P-256 key stored in iCloud Keychain. Available on all your Apple devices. Touch ID enforced at app level before signing. - Device-only
[n]— Hardware-backed Secure Enclave key. Never leaves the chip. Touch ID enforced by hardware during signing. Only works on this device.
Typical Flow#
- Generate a key — Tab 1, press
n, enter a label, pressEnter - Set it active — Press
son the key - Log in to your PDS — Tab 6, enter handle and app password
- Enter your DID — Tab 2, press
e, enter yourdid:plc:... - Add key to rotation — Tab 2, press
aon your key - Sign the operation — Tab 3, press
s, authenticate with Touch ID - Submit — Confirm submission to PLC directory
Architecture#
src/
├── main.rs # Entry point, terminal setup/teardown
├── app.rs # Application state, event loop, async task dispatch
├── enclave.rs # Secure Enclave + iCloud Keychain key management
├── didkey.rs # did:key encoding/decoding (P-256)
├── plc.rs # PLC operations, DAG-CBOR serialization, CID computation
├── sign.rs # DER→raw signature conversion, low-S normalization
├── directory.rs # PLC directory HTTP client
├── atproto.rs # AT Protocol XRPC client (session, posts)
├── event.rs # Async message types
└── ui/
├── mod.rs # Top-level layout, tab bar, modals
├── keys.rs # Key list and management
├── identity.rs # DID document display
├── operations.rs# Operation signing and diff view
├── audit.rs # Audit log browser
├── login.rs # PDS authentication
├── post.rs # Post composer
└── components.rs# Shared widgets
Signing Flow#
PLC Operation (JSON)
→ serialize_for_signing() (DAG-CBOR, canonical key ordering)
→ sign_operation()
→ SE key: SecKeyCreateSignature (hardware Touch ID)
→ Software key: LAContext biometric check → SecKeyCreateSignature
→ DER → raw r||s (64 bytes)
→ low-S normalization
→ base64url encode → sig field
→ compute CID → submit to plc.directory
Development#
# Run tests (no hardware required)
cargo test
# Build without signing (for development)
cargo build
# Build + codesign (required for Secure Enclave access)
./build.sh
License#
MIT