# ELAI chip-helper A single-file Python HTTP bridge that gives ELAI ecosystem browser pages access to a chip-card reader, bypassing the macOS WebUSB + CryptoTokenKit conflict. ## What problem this solves On macOS, the system smart-card framework (CryptoTokenKit / `ifdreader`) claims CCID readers exclusively. SIP (System Integrity Protection) prevents userspace from disabling that claim. WebUSB in Chrome therefore can't see the CCID interface — it shows up as "No CCID interface found on this device." This helper sidesteps the whole conflict: it uses **pyscard**, which talks to **PC/SC**, which **IS** the system smart-card framework. We're using CryptoTokenKit as an API instead of fighting it. The chip event JSON shape and the AID candidate list are byte-compatible with `chip-protocol.js`, so the chip fingerprint derived here matches what the WebUSB transport would have produced. KEK derivation, Ed25519 wrap, and ledger enrollment downstream work identically. ## Setup (one time) You need Python 3.9+ (preinstalled on macOS Catalina+) and `pyscard`. ```bash pip3 install pyscard ``` If pyscard fails to install with a compiler error, install Xcode Command Line Tools first: ```bash xcode-select --install ``` Then re-run the pip install. ## Run From this directory: ```bash python3 chip-helper.py ``` You'll see a banner showing it's listening on `http://127.0.0.1:8001`. Leave the terminal open. Ctrl-C to stop. ## Verify it works In a new terminal, with a chip card inserted in your reader: ```bash # Reader + ATR check curl http://localhost:8001/health # Full protocol run curl -X POST http://localhost:8001/chip-event ``` You should get JSON back. Example for a Visa card: ```json { "ok": true, "eventType": "iso7816-select-only", "transport": "pcsc", "reader": "ACS ACR39U ICC Reader", "cardLabel": "Visa Credit/Debit", "cardClass": "emv", "aid": "A0000000031010", "atr": "3B68000000...", "selectResponse": { "data": "6F26...", "sw": "9000" }, "authResponse": { "data": "", "sw": "6700", "challenge": "..." }, "capturedAt": "2026-06-06T16:42:11.123Z", "durationMs": 412, "errors": [ "card Visa Credit/Debit declined INTERNAL AUTHENTICATE (SW=6700, civilian EMV) — recorded as presence-only event" ] } ``` `eventType: "iso7816-select-only"` for civilian EMV (polite refusal) is correct, not an error — the card was present, selected cleanly, and just declined INTERNAL AUTHENTICATE outside a full EMV transaction. Federal cards (PIV, CAC) return `eventType: "iso7816-internal-auth"` with a real signature in `authResponse.data`. ## Use with the ELAI ledger console Open the v2 console at `https://americafirst4us.com/ledger/` and click the "Enroll via local helper" button (once wired — see Task #178). The console will POST to `http://localhost:8001/chip-event`, get back the event, derive a KEK from the chip fingerprint (SHA-256 of AID + selectResponse.data), wrap an Ed25519 keypair, and enroll the public key in the ELAI ledger. Same data flow as the WebUSB path — just uses PC/SC instead of WebUSB under the hood. ## CORS The helper allows requests from the ELAI ecosystem origins: - `americafirst4us.com` - `idregulators.com` - `verifythecard.com` - `4pdfs.com` - `localhost` Browser → `http://localhost:8001` from an `https://` page is allowed by Chrome since v94 (localhost is a "potentially trustworthy URL"). No mixed- content blocking, no extra config needed. ## Troubleshooting ### "no readers found" The OS doesn't see any CCID reader. Check: - Reader is plugged into USB - It's actually a CCID-class smart card reader (not a magstripe-only swipe reader, not a USB HID-mode reader) - macOS's smart-card services are running: ```bash launchctl list | grep ifd ``` If `com.apple.ifdreader` isn't there, the reader driver isn't loaded. Reboot usually fixes it. ### "no card inserted" Reader is found and connected, but slot is empty. Insert a chip card. ### "Address already in use" on startup Another instance of `chip-helper.py` is already running, or something else is using port 8001. Find it: ```bash lsof -i :8001 ``` Kill the offending process, or edit `chip-helper.py` to use a different `PORT`. ### Browser can't reach `localhost:8001` - Make sure the helper is actually running (you'll see the banner) - Confirm the origin you're calling from is in `ALLOWED_ORIGINS` (top of the Python file) - Some corporate VPNs block localhost in unusual ways — disconnect VPN to test ## Architecture context `chip-helper.py` is the **Transports** layer for desktop, parallel to the existing transports: | Transport | Where it runs | Status | | ------------------ | ------------------------ | ------ | | WebUSB CCID | Chrome / Edge desktop | Blocked on macOS by CTK | | **PC/SC (this)** | Python local helper | **Works on macOS, Linux, Windows** | | CoreNFC (iOS) | Capacitor mobile app | Works | | IsoDep (Android) | Capacitor mobile app | Works | All four transports produce the same event JSON shape and feed into the same upstream KEK derivation and ledger enrollment. Single source of truth for the protocol layer is `chip-protocol.js` (browser) and this file (Python) — both implement the same ISO 7816-4 dance against the same AID candidate list. --- AmericaFirst4Us Inc. · ELAI ecosystem · US Patent Application 17/085,257 and CIP — both pending USPTO examination.