a simple rust terminal ui (tui) for setting up alternative plc rotation keys driven by: secure enclave hardware (not synced) or software-based keys (synced to icloud)
plc
secure-enclave
touchid
icloud
atproto
1# plc-touch
2
3Please Touch. Secure enclave based keys for ATProto PLC rotation keys.
4
5> Named after the [Please Touch Museum](https://www.pleasetouchmuseum.org/)
6
7A Rust TUI for managing AT Protocol (Bluesky) `did:plc` rotation keys with macOS Secure Enclave and Touch ID.
8
9Take 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.
10
11## Features
12
13- **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)
14- **Touch ID Signing** — Every PLC operation signing triggers biometric authentication
15- **DID Inspection** — View your DID document, rotation keys, verification methods, and services
16- **PLC Operations** — Add/remove rotation keys, with diff preview before signing
17- **Audit Log** — Browse the full PLC operation history for any DID
18- **PDS Login** — Authenticate with your PDS for operations that require it (initial key addition via email token flow)
19- **Test Posts** — Send posts to Bluesky from the TUI
20
21## Screenshots
22
23```
24┌─plc-touch──did:plc:abc...xyz──🔑 mykey ● PDS─┐
25│ 1 Keys │ 2 Identity │ 3 Sign │ 4 Audit │ ...│
26├───────────────────────────────────────────────┤
27│ ┌ Secure Enclave Keys ───────────────────────┐│
28│ │ ▸ mykey * ││
29│ │ did:key:zDnae... ││
30│ │ iCloud Keychain (synced) Touch ID ││
31│ └────────────────────────────────────────────┘│
32│ q quit ? help 1-6 tabs n new d del s set │
33└───────────────────────────────────────────────┘
34```
35
36## Requirements
37
38- macOS 13+ (Ventura or later)
39- Rust toolchain
40- Apple Developer account (for Secure Enclave entitlements)
41- Provisioning profile with `keychain-access-groups` entitlement
42
43## Setup
44
451. **Clone and configure:**
46
47```bash
48git clone https://github.com/yourusername/plc-touch.git
49cd plc-touch
50cp .env.example .env
51```
52
532. **Edit `.env`** with your Apple Developer signing details:
54
55```
56CODESIGN_IDENTITY="Apple Development: Your Name (XXXXXXXXXX)"
57BUNDLE_ID="com.yourcompany.plc-touch"
58TEAM_ID="XXXXXXXXXX"
59```
60
613. **Create a provisioning profile** on [developer.apple.com](https://developer.apple.com):
62 - Register your Mac's Provisioning UDID (find it in System Settings > General > About, or `system_profiler SPHardwareDataType | grep "Provisioning UDID"`)
63 - Create a macOS App ID with your bundle ID
64 - Create a macOS Development provisioning profile
65 - Download and save as `embedded.provisionprofile` in the project root
66
674. **Build and sign:**
68
69```bash
70./build.sh
71```
72
735. **Run:**
74
75```bash
76target/release/plc-touch.app/Contents/MacOS/plc-touch
77```
78
79## Usage
80
81### Tabs
82
83| Tab | Key | Description |
84|-----|-----|-------------|
85| Keys | `1` | Manage Secure Enclave / iCloud Keychain keys |
86| Identity | `2` | Inspect DID document, rotation keys, verification methods |
87| Sign | `3` | Review and sign staged PLC operations |
88| Audit | `4` | Browse PLC operation audit log |
89| Post | `5` | Send a test post to Bluesky |
90| Login | `6` | Authenticate with your PDS |
91
92### Key Bindings
93
94**Global:**
95- `1`-`6` — Switch tabs
96- `?` — Help
97- `q` — Quit
98
99**Keys tab:**
100- `n` — Generate new key (choose syncable or device-only)
101- `d` — Delete selected key
102- `s` — Set as active signing key
103- `Enter` — Copy `did:key` to clipboard
104
105**Identity tab:**
106- `e` — Enter/change DID
107- `r` — Refresh from PLC directory
108- `a` — Add active key to rotation keys
109- `x` — Remove selected rotation key
110- `m` — Move rotation key (change priority)
111
112**Sign tab:**
113- `s` — Sign operation with Touch ID
114- `j` — Toggle JSON view
115
116**Audit tab:**
117- `j`/`Enter` — Expand/collapse entry
118
119### Key Types
120
121When generating a key (`n`), you can toggle sync with `Tab`:
122
123- **Syncable `[Y]`** — Software P-256 key stored in iCloud Keychain. Available on all your Apple devices. Touch ID enforced at app level before signing.
124- **Device-only `[n]`** — Hardware-backed Secure Enclave key. Never leaves the chip. Touch ID enforced by hardware during signing. Only works on this device.
125
126### Typical Flow
127
1281. **Generate a key** — Tab 1, press `n`, enter a label, press `Enter`
1292. **Set it active** — Press `s` on the key
1303. **Log in to your PDS** — Tab 6, enter handle and app password
1314. **Enter your DID** — Tab 2, press `e`, enter your `did:plc:...`
1325. **Add key to rotation** — Tab 2, press `a` on your key
1336. **Sign the operation** — Tab 3, press `s`, authenticate with Touch ID
1347. **Submit** — Confirm submission to PLC directory
135
136## Architecture
137
138```
139src/
140├── main.rs # Entry point, terminal setup/teardown
141├── app.rs # Application state, event loop, async task dispatch
142├── enclave.rs # Secure Enclave + iCloud Keychain key management
143├── didkey.rs # did:key encoding/decoding (P-256)
144├── plc.rs # PLC operations, DAG-CBOR serialization, CID computation
145├── sign.rs # DER→raw signature conversion, low-S normalization
146├── directory.rs # PLC directory HTTP client
147├── atproto.rs # AT Protocol XRPC client (session, posts)
148├── event.rs # Async message types
149└── ui/
150 ├── mod.rs # Top-level layout, tab bar, modals
151 ├── keys.rs # Key list and management
152 ├── identity.rs # DID document display
153 ├── operations.rs# Operation signing and diff view
154 ├── audit.rs # Audit log browser
155 ├── login.rs # PDS authentication
156 ├── post.rs # Post composer
157 └── components.rs# Shared widgets
158```
159
160### Signing Flow
161
162```
163PLC Operation (JSON)
164 → serialize_for_signing() (DAG-CBOR, canonical key ordering)
165 → sign_operation()
166 → SE key: SecKeyCreateSignature (hardware Touch ID)
167 → Software key: LAContext biometric check → SecKeyCreateSignature
168 → DER → raw r||s (64 bytes)
169 → low-S normalization
170 → base64url encode → sig field
171 → compute CID → submit to plc.directory
172```
173
174## Development
175
176```bash
177# Run tests (no hardware required)
178cargo test
179
180# Build without signing (for development)
181cargo build
182
183# Build + codesign (required for Secure Enclave access)
184./build.sh
185```
186
187## License
188
189MIT