Commit 4807e17
committed
iot/demo: per-Pramaan — sensor for capture+match only, host owns everything else
Previously the sensor's flash slot was load-bearing: signup wrote the
template at slot N, login did a 1:N search across the sensor's library,
and the host stored {email, slot}. That capped the demo at 1000
accounts AND meant the sensor was the source of truth for "who's
enrolled."
This refactor inverts the relationship per the patent's intent. The
sensor is reduced to two roles:
1. capture+combine to produce the stable template (signup)
2. 1:1 MATCH between a fresh capture and a host-supplied template
(login)
The host owns the template, the commitment, and the proof. Capacity
is bound by disk, not by sensor flash.
sensor.ts
- downloadCharacteristic(buffer, data): DOWN_CHAR (0x09) opcode +
followup data packets terminated by PID.END_DATA. Chunks the
template to the sensor's configured packet size (128 B by default
on R307). Used by the login flow to push the host's stored
template back into buf2 right before MATCH.
- match(): MATCH (0x03) opcode. Returns {score} on CONF.OK, null on
CONF.NOT_MATCH. R307 score range 0–300+ at security level 3; well
above MATCH_THRESHOLD = 50 for the same finger.
crypto.ts
- biometricId() now hashes the actual template bytes, not a synthetic
slotSeed(slot, pepper). Same Patent-Claim-3 construction, real
biometric input.
- deriveSignals() takes templateBytes instead of {slot, pepper}. The
pepper concept is gone — the template IS the secret. Same Poseidon
derivation downstream.
bridge.ts
- Account schema: drops `slot`; adds `template` (base64 of the 768-byte
R307 template). isValidAccount tightened to match.
- nextFreeSlot() deleted.
- enroll(): capture 1 → lift → capture 2 → combine → upload via
UpChar → derive signals from templateBytes → Groth16 prove + verify
→ persist {email, template, salt, commitment, didHash,
identityBinding, did, createdAt}. Sensor flash never written.
- authenticate(): capture fresh → imageToCharBuffer(1) → look up
account → downloadCharacteristic(2, storedTemplate) → match() →
if score ≥ MATCH_THRESHOLD: re-derive (using stored salt for
determinism), prove, public-signal-check, verify. Any divergence
between recomputed and stored public signals is treated as account
tampering (proof_failed).
- reset(): no longer emptyDatabase()s the sensor. Host-only.
- New Phase events: uploading_template, loading_template, matching.
Per the streaming UI's contract; old `storing` + `searching` are
retired because neither operation happens anymore.
iot/demo/index.html
- Hero copy rewritten to describe the new flow.
- Sign-up card subtitle: "combines them into a stable template, uploads
it to the host, derives a Poseidon commitment…"
- Log-in card subtitle: "host pushes the stored template back into the
sensor and asks for a 1:1 match…"
- New phase handlers — uploading_template, loading_template, matching
— all working-mood spinners with explanatory subline.
- Accounts table swaps the Slot column for DID (last 12 chars).
- Reset button + dialog updated to say "Clear all accounts" (sensor
flash isn't being wiped because we never used it).
Tested
- typecheck clean across crypto.ts, proof.ts, sensor.ts, bridge.ts
- bridge boots, preloads Groth16 keys, opens the serial port (when the
R307 is connected)
- Legacy {email, slot, ...} entries from the prior schema are detected
and skipped at load time — operator re-signs up under the new schema1 parent c4f96cd commit 4807e17
4 files changed
Lines changed: 170 additions & 116 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
280 | 280 | | |
281 | 281 | | |
282 | 282 | | |
283 | | - | |
284 | | - | |
285 | | - | |
286 | | - | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
287 | 288 | | |
288 | 289 | | |
289 | 290 | | |
290 | 291 | | |
291 | 292 | | |
292 | 293 | | |
293 | 294 | | |
294 | | - | |
| 295 | + | |
295 | 296 | | |
296 | 297 | | |
297 | 298 | | |
| |||
311 | 312 | | |
312 | 313 | | |
313 | 314 | | |
314 | | - | |
| 315 | + | |
315 | 316 | | |
316 | 317 | | |
317 | 318 | | |
| |||
328 | 329 | | |
329 | 330 | | |
330 | 331 | | |
331 | | - | |
| 332 | + | |
332 | 333 | | |
333 | 334 | | |
334 | | - | |
| 335 | + | |
335 | 336 | | |
336 | 337 | | |
337 | 338 | | |
338 | 339 | | |
339 | | - | |
| 340 | + | |
340 | 341 | | |
341 | 342 | | |
342 | 343 | | |
| |||
500 | 501 | | |
501 | 502 | | |
502 | 503 | | |
503 | | - | |
| 504 | + | |
504 | 505 | | |
505 | 506 | | |
506 | 507 | | |
507 | | - | |
508 | | - | |
| 508 | + | |
| 509 | + | |
509 | 510 | | |
510 | 511 | | |
511 | 512 | | |
| |||
593 | 594 | | |
594 | 595 | | |
595 | 596 | | |
596 | | - | |
| 597 | + | |
597 | 598 | | |
598 | 599 | | |
599 | 600 | | |
600 | | - | |
601 | | - | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
602 | 612 | | |
603 | 613 | | |
604 | 614 | | |
| |||
643 | 653 | | |
644 | 654 | | |
645 | 655 | | |
646 | | - | |
| 656 | + | |
647 | 657 | | |
648 | 658 | | |
649 | 659 | | |
| |||
685 | 695 | | |
686 | 696 | | |
687 | 697 | | |
688 | | - | |
| 698 | + | |
689 | 699 | | |
690 | 700 | | |
691 | 701 | | |
| |||
721 | 731 | | |
722 | 732 | | |
723 | 733 | | |
724 | | - | |
| 734 | + | |
725 | 735 | | |
726 | 736 | | |
727 | 737 | | |
| |||
730 | 740 | | |
731 | 741 | | |
732 | 742 | | |
733 | | - | |
| 743 | + | |
734 | 744 | | |
735 | 745 | | |
736 | 746 | | |
| |||
750 | 760 | | |
751 | 761 | | |
752 | 762 | | |
753 | | - | |
| 763 | + | |
754 | 764 | | |
755 | 765 | | |
756 | 766 | | |
757 | | - | |
| 767 | + | |
758 | 768 | | |
759 | 769 | | |
760 | 770 | | |
| |||
0 commit comments