BeaconTruth
Authenticated Bluetooth location beacons. Every advertisement is one link of a hash chain — verifiable by anyone, forgeable by nobody — so a position report can be trusted, not just received.
The service
Generate
A beacon makes its own identity the first time it builds a chain: a root drawn from the die's own noise, sealed into a slot it can never rewrite or read back. No secret is programmed in at the factory, so there is nothing in a factory to steal.
Register
Commissioning is hearing one advertisement. The anchor is computed from the packet — never accepted from the caller — so registering a beacon proves it holds a chain, and nothing has to be read out of the device to do it.
Resolve
Each packet carries the next link backwards along that chain, and verifying one is hashing it forward until the anchor appears. Forgeries and replays are refused; what survives becomes trusted location data.
One standard packet
Thirty-one bytes of advertising data, in two standard AD structures: the 16-bit service UUID list, then service data carrying a 23-byte payload. The UUID appears in both because iOS hands a background scan no service data unless it also appears in the list.
The token is one link of a hash chain. The beacon walks 223 links forward from a seed it never reveals, publishes only where that walk ended, and then broadcasts the chain backwards, one link a minute for about sixteen years — so hearing today's token tells you nothing about tomorrow's. The index says which link it is.
Verifying is hashing forward. Hash the token index + 1 times and you reach the beacon's anchor, which is public: a hash that proves a beacon without letting anyone impersonate it. A wrong index lands somewhere else and fails, so the token authenticates the moment it claims as well as itself. The two health bytes — battery and die temperature — sit outside the chain and are not authenticated at all. Anyone can forge them onto a replayed packet, and nothing should be built on them.
No device ID on the wire, and no stable address either: the beacon advertises from a private address it redraws on the same sixty-second boundary the token turns over. Every beacon still has an ID — ten bytes, written as sixteen Crockford symbols and printed on the hardware — and its anchor is registered against that at commissioning. Binding the two once, there, is what lets the packet stop repeating it.
03 03 d907
1a 16 d907 01e240 08a43d8f66d9e0c9c0fa095885bfc3541134 2a17
One advertisement, and a token you can check for yourself. It sits at
index 123 456; SHA-256 it 123 457 times, truncating to eighteen
bytes each round, and you land on
a08130e65feae4a6b2870c6ecda4f5104835 — the anchor. No key
was involved in that, which is the point.
Nothing to steal
There is no shared secret anywhere in this system. No secret is programmed into a beacon at manufacture and nothing is read out of one to register it; the chain root never leaves the die it was generated on; and we hold no key that would let us — or anyone who compromised us — produce a token for a beacon we do not have. Every anchor we store is a hash that authorizes nothing: leaking the lot would let an attacker verify beacons, which is exactly what we publish them for.
Open by design
The packet format, the chain construction, and the registration protocol are fixed and fully specified — nothing here is meant to be reverse-engineered from a scanner. Every beacon's anchor is published in a public registry, rebuilt daily and signed with a key that never leaves its hardware module, so you can verify a packet offline and never have to take our word for one.