NAC sign closed: full validation stamp computes pure-code from inputs; README updated

The tail threshold cipher and pre-init region closed via empirical fit
against the 270 checkpointed rounds — pure-Python model (no emulator, no
captures) reproduces sig16 and the full 517-B stamp byte-exact (verify
20/20, independently re-verified). Spec rev 30 residue line corrected;
README: anisette chain now includes the NAC mint (Kotlin signature port
next).
This commit is contained in:
fenleon committed 2026-10-08 18:18:18 +02:00
1 parent 6e50bf6602
commit ebabd37aef
2 files changed
+5 -6

No files matched your search

+3 -4
View File
@@ -1,6 +1,6 @@
# Open Madrid
An open implementation of Apple's madrid protocol (iMessage) in Kotlin. Covers the property-list codecs, the APNs "courier" push client, the IDS identity service, the encryption envelope, the registration/activation chain, and the ADI anisette chain (device provisioning and per-request OTP headers) computed fully locally in Kotlin.
An open implementation of Apple's madrid protocol (iMessage) in Kotlin. Covers the property-list codecs, the APNs "courier" push client, the IDS identity service, the encryption envelope, the registration/activation chain, and the ADI anisette chain (device provisioning, per-request OTP headers, and the validation-stamp "NAC" mint) computed fully locally in Kotlin.
Unlike [open-absinthe](https://github.com/JJTech0130/open-absinthe), which is a mock placeholder with no real code, everything here is readable and Apache-2.0 licensed.
@@ -12,13 +12,12 @@ Validated:
- The registration chain ran live against Apple (2026-10-02→04, spec rev 26): Albert activation, the packed APNs courier, the full GSA sign-in (SRP, trusted-device 2FA, PET delivery, postdata), then IDS authenticate and register — both green, `mailto:` handle active. The earlier 409 refusals turned out to be Apple's validation-stamp replay guard (one mint = one device record), documented in the spec.
- Two live unauthenticated probes against Apple succeeded: both bag endpoints return plists this stack parses, and certificate pinning validates Apple's real TLS chains. A drift check ships with the repo (`:engine:runProbe`).
- The courier's auth model is settled: the packed path needs no client certificate; the legacy path answers the handshake with a TLS 1.3 post-handshake `certificate_required` alert.
- The ADI anisette chain is reimplemented natively, no emulation or helper binary: the white-box OTP ciphers, the GSA provisioning exchange, and the full spim/cpim/ptm wire framing are transcribed clean-room from analysis of a compiled ADI implementation, verified byte-exact against oracle vectors, then live-pinned against three genuine provisioning runs under an instrumented debugger. Every byte group of the exchange is now identified, including the cpim tail's SHA-256 seal over the encrypt output and the spim trailing's signature (195 tests green, spec rev 29). No anisette server, no Unicorn, no Mac relay.
- The ADI anisette chain is reimplemented natively, no emulation or helper binary: the white-box OTP ciphers, the GSA provisioning exchange, the full spim/cpim/ptm wire framing, and the validation-stamp ("NAC") mint — pear white-box cipher, blob assembly, and the 16-byte OTS signature — are transcribed clean-room from analysis of a compiled ADI implementation, verified byte-exact against oracle vectors and live captures (three genuine provisioning runs plus a validation-stamp capture under an instrumented debugger). Every byte group of the exchange and of the 517-byte stamp is identified and reproduced; the full stamp computes byte-exact from its inputs (python reference model — the Kotlin signature port is the next step; 206 tests green, spec rev 30). No anisette server, no Unicorn, no Mac relay.
Not validated yet:
- No real message send or receive over the courier; renewal across sessions is untested.
- The crypto envelopes have round-trip tests but no known-answer vectors from a live device.
- The validation-blob ("NAC") mint — the per-device hardware signature Apple's registration accepts — is the one ADI-adjacent piece not yet reimplemented; the analysis plan and method are in the spec and the workspace worklog.
- A few wire details are capture-bound guesses, tracked in the spec's open-questions checklist.
- PQ3 is unsupported.
@@ -49,7 +48,7 @@ This keeps the code fully open and acceptable to F-Droid and other distribution
No Apple-derived code or binary ships here, including the IMDAppleServices framework. The bundled identity in `registration/src/main/resources/imessage/fairplay/` is a synthetic placeholder, generated and self-signed, for tests only. Live activation requires Apple's real FairPlay identity, which each user stages themselves.
One deliberate exception in spirit, documented for auditability: the ClearADI white-box lookup tables (the constants the ADI OTP cipher needs) are constant *data* reconstructed by analyzing a compiled ADI implementation, and they ship as generated Kotlin source (`ClearAdiTablesData.kt`) decoded at startup — no Apple code, binary, or resource file is committed. The extraction method and every derived fact are documented in the spec.
One deliberate exception in spirit, documented for auditability: the ClearADI and pear white-box lookup tables (the constants the ADI OTP cipher and the NAC mint need) are constant *data* reconstructed by analyzing a compiled ADI implementation, and they ship as generated Kotlin source (`ClearAdiTablesData.kt`, `PearTablesData.kt`) decoded at startup — no Apple code, binary, or resource file is committed. The extraction method and every derived fact are documented in the spec.
## Building