silentpayments.net
Detail
plain words, no jargon the standards, named every number, and how to check it

For airgapped signers

Hold this up
to the device

A hardware wallet has no clock, so it cannot tell a valid proof from one that expired last month. This code carries the time across.

BIP-353 names are proved with DNSSEC, and an RFC 9102 proof is only valid inside a signature window measured in days. Checking that window needs a date. A signer has no battery-backed clock and no network, so the date has to arrive the same way everything else does: through the camera.

§ 01 · The code

—

Reading the clock…

oT…

It refreshes on its own every 20 seconds. Anything within a few hours is close enough for the check the device does, so there is no rush.

§ 02 · The one rule

Use a different device

Show this page on your phone, not on the computer that built the transaction.

If one machine hands the signer both the payment and the time, and that machine has been tampered with, it can pick a time that makes a fake name look real. A second screen breaks that. A compromised coordinator can supply a forged DNSSEC proof together with a date chosen to fall inside that forgery's validity window. Both halves then agree, and the device has no way to disbelieve either. Sourcing the timecode from a device the coordinator does not control removes the second half.

§ 03 · What this is not

It is not signed, and it should not be

We could sign this number with our key. We deliberately do not, and the reason is worth reading before anyone asks us to.

A signature proves where, not when

It would prove the number came from us. It would say nothing about whether the number is now, and now is the only thing that matters here.

An old signed code replays perfectly

Hand the device a genuine, correctly signed timecode from three weeks ago and it verifies. Catching that would need a clock, and the missing clock is the whole problem. So the signature adds cost and ceremony while defending against nothing the attacker was going to do.

It would put us inside your signing path

This site argues you should not have to trust its operator. Making a signer depend on our key to approve a payment would contradict that on the one screen where it matters most.

You are the clock. You read the time on the screen, you know whether it is roughly now, and only then do you scan. The device is trusting your eyes, not our server.

§ 04 · If you skip it

No timecode means not verified

Without a date the proof cannot be checked, so the device knows nothing about the name. It has to say so as loudly as it would say verified. A quiet fallback reads as approval to everyone who is not hunting for a missing badge.

What happenedWhat the device knowsWhat it must show
Timecode scanned, proof valid The name resolves to this address Verified, and the time it checked against
Timecode scanned, proof expired The proof is bad Not verified, and why
No timecode Nothing about the name Not verified, no date available

The middle row and the bottom row are different failures, and a person can act on the difference, so a device should not collapse them into one message.

§ 05 · For implementers

The format is not ours

This is the GoPro Labs precision time command, and ShieldSigner already decodes it. So a Doomsigner build reads this page today, with no firmware change at all.

oT<YYMMDDHHMMSS>

Twelve digits, zero-padded, UTC: two-digit year, month, day, hour, minute, second. oT260903001500 is 14 bytes and means 2026-09-03 00:15:00 UTC. That fits a version 1 code at error correction level L, so it scans at once on a 240×240 panel with a fixed-focus camera.

The device's own rule

^oT(\d{12}(\.\d{2})?|0)$, then the year read as 2000 + YY. The optional fractional part and the bare oT0 belong to the GoPro format; we emit neither.

What it does with it

Decodes to a datetime and runs date -s. The clock holds until the next reboot, which is the window an RFC 9102 check needs.

It does not persist

And it should not. A signer that remembered a scanned time across a reboot would be claiming a clock it does not have.

The same moment as JSON: /api/time.