README.md (5705B)
1 # ๐ OnlyN00bs โ a DEF CON 34 friend-finder badge 2 3 A badge for a friend group: each badge broadcasts your handle and shows the handles of 4 other crew badges in range โ sorted by signal strength, so the closest friends float to 5 the top. Built to be **spoof-proof in the worst RF environment on earth**: beacons are 6 HMAC-signed with a shared group key, so randos and impersonators never make it onto your 7 screen. 8 9 ``` 10 you: crash_override โโ 4 nearby โโโโโโโโโโ 11 โโโโโ acid_burn -52 dBm 12 โโโโ cereal_killer -61 dBm 13 โโโ lord_nikon -73 dBm 14 โโ phantom_phreak -88 dBm 15 ``` 16 17 User guide (setup, screens, button, battery, troubleshooting): 18 [badge.virtualshack.io](https://badge.virtualshack.io). 19 20 ## Hardware 21 22 An off-the-shelf **FireBeetle 2 ESP32-E** (onboard LiPo charger + JST-PH) driving a 23 **2.42" SSD1309 mono OLED** off a **2000 mAh LiPo**, one push button, in a 3D-printed case. 24 Parts: [`hardware/BOM.md`](hardware/BOM.md). Case files: [`hardware/cad/`](hardware/cad/). 25 26 ## Layout 27 28 ``` 29 firmware/ PlatformIO project (Arduino-ESP32 core 3.x) 30 platformio.ini build envs (below) 31 src/ 32 config.h channel, intervals, BLE UUIDs, pins 33 secrets.h.example template for your crew's group key (copy to secrets.h) 34 beacon.h signed wire format + HMAC sign/verify 35 peers.h bounded, flood-resistant peer table 36 encounters.h LittleFS encounter log + report aggregation 37 clock.h soft real-time clock (BLE-seeded, NVS-checkpointed) 38 points.h ยท points_history.h ยท pet.h ยท battery.* 39 display_oled.cpp the badge display (U8g2) 40 main.cpp mode state machine (provisioning / discovery / views) 41 provisioning/ 42 index.html Web Bluetooth setup app โ handle, avatar, clock, metrics export 43 web/src/ the site at badge.virtualshack.io โ static, no build step; the 44 service worker makes it (and the setup app) work offline 45 hardware/ 46 BOM.md parts for one badge 47 cad/ case generators (pure Python โ STL) + the production STLs 48 docs/ 49 hmac-beacon-auth.md the beacon signing scheme and its limits 50 provisioning.md the BLE setup protocol 51 docker.md reproducible build container 52 drivers/ USB-serial driver note for flashing from macOS 53 ``` 54 55 ## How it works 56 57 **Setup (BLE).** In setup mode the badge advertises a BLE GATT service and shows a fresh 58 3-character pairing code. Open `provisioning/index.html` in Chrome or Edge (Web Bluetooth 59 โ not available on iOS), connect, enter the code, then set a handle, avatar and clock. The 60 handle is sanitized (printable ASCII, โค 24 bytes) on both sides and stored in NVS. Setup 61 only listens while the badge is in setup mode. Details: [`docs/provisioning.md`](docs/provisioning.md). 62 63 **Discovery (ESP-NOW).** The badge broadcasts a signed beacon about once a second on a 64 fixed channel. Incoming beacons are HMAC-verified against the group key *before* anything 65 touches the peer table; the table is bounded and ages entries out, so a flood of garbage 66 can't exhaust memory or fill the screen. 67 68 **Encounters, points, avatar.** Each continuous stretch near a friend is logged to 69 LittleFS. The badge ranks friends by time together, awards points for time spent near crew, 70 graphs them over the con, and runs an ASCII avatar that reacts to events. The setup app 71 exports the logs and points over BLE to charts, PDF and JSON โ nothing leaves your browser. 72 73 ## Security model 74 75 Full mechanism and limits: [`docs/hmac-beacon-auth.md`](docs/hmac-beacon-auth.md). 76 77 - **Shared group key.** Beacon = `{magic, version, counter, handle, HMAC-SHA256(key, โฆ)}`. 78 Verification failure โ silent drop. That filters outsiders and spoofers. 79 - **It signs, it does not encrypt.** Anyone listening on 2.4 GHz can read handles and 80 follow a badge. Pick a handle you're happy to have in the air. 81 - **`counter`** jumps forward each boot, so captured beacons can't be replayed as fresher. 82 - **Handles are untrusted input.** A handle set over BLE is clamped to printable ASCII 83 (โค 24 bytes) before it's stored; a received handle must carry a valid signature and pass 84 a 1โ24 byte length check, but its bytes aren't filtered โ a key holder can send any 85 byte values. 86 87 ## Build and flash 88 89 ```sh 90 cp firmware/src/secrets.h.example firmware/src/secrets.h 91 # put your crew's key in it: openssl rand -hex 32 92 cd firmware 93 pio run -e oled_v3_prod -t upload # refuses to build without a real key 94 pio device monitor 95 ``` 96 97 Every badge in a crew needs the **same** key; badges with different keys can't see each 98 other. `oled_v3` is the same firmware without the key check, for development. Prefer no 99 host toolchain: [`docs/docker.md`](docs/docker.md). Then open `provisioning/index.html` 100 from `localhost` (a secure context, so Web Bluetooth works) to set the badge up. 101 102 ## License 103 104 | what | paths | license | 105 |---|---|---| 106 | Code | `firmware/`, `provisioning/`, `web/src/` (HTML, CSS, JS), `hardware/cad/*.py`, `Dockerfile` | [MIT](LICENSE) | 107 | Case models, docs, photos | `hardware/cad/stl/`, `docs/`, `*.md`, `web/src/assets/img/` | [CC BY-SA 4.0](LICENSE-CC-BY-SA-4.0.txt) | 108 109 Libraries are fetched at build time and keep their own licenses (arduino-esp32 LGPL-2.1, 110 ESP-IDF Apache-2.0, NimBLE-Arduino Apache-2.0, U8g2 BSD-2-Clause) โ relevant if you 111 redistribute a compiled firmware image. 112 113 Attribution: **virtualtack** โ [badge.virtualshack.io](https://badge.virtualshack.io). 114 See [`SNAPSHOT.md`](SNAPSHOT.md) for what this repository deliberately leaves out.