[Feature] Check the RFC 3161 nonce echo on import #563

Closed
opened 2026-07-22 15:09:52 +00:00 by brenno · 0 comments
Owner

The request already carries a random nonce, and RFC 3161 §2.4.2 obliges the TSA to echo it back. That echo binds one request to one token and defeats replay of an older token for the same imprint. OciDeck sends it but never checks it: the deck does not keep the nonce, so after a restart the other half is gone.

The reason originally recorded for not keeping it — that a new key would clash with the seal's in-flight move to a sidecar — has lapsed. That move landed, and <name>.seal.json is now exactly where an opaque, document-scoped value like this belongs. rfc3161_timestamp.dart says so itself; what is left is the decision to build it.

Shape:

  • SealRecord gains the pending request nonce (hex). Additive key in .seal.json, no version bump — older builds must keep ignoring it rather than refusing the whole sidecar.
  • _exportTsq stores the nonce it generated; _importTsr calls the existing timeStampEchoesNonce and refuses a token that does not echo it.
  • One new l10n string (a nonce mismatch is a different failure from an imprint mismatch and deserves its own sentence), so 31 translations.
  • Touches the file format, so a short design note comes first.

Explicitly NOT in scope: CMS signature and certificate-chain verification of the token. That reasoning is recorded in rfc3161_timestamp.dart and SECURITY_DESIGN §9 and still holds — X.509 path validation means a new dependency plus a bundled trust-anchor list that ages by definition, in an application that makes no network connection and promises tamper-evidence, not tamper-proofing.

Split out of #516 so that issue can close once its remaining items are done.

The request already carries a random nonce, and RFC 3161 §2.4.2 obliges the TSA to echo it back. That echo binds one request to one token and defeats replay of an older token for the same imprint. OciDeck sends it but never checks it: the deck does not keep the nonce, so after a restart the other half is gone. The reason originally recorded for not keeping it — that a new key would clash with the seal's in-flight move to a sidecar — has lapsed. That move landed, and `<name>.seal.json` is now exactly where an opaque, document-scoped value like this belongs. `rfc3161_timestamp.dart` says so itself; what is left is the decision to build it. Shape: - `SealRecord` gains the pending request nonce (hex). Additive key in `.seal.json`, no version bump — older builds must keep ignoring it rather than refusing the whole sidecar. - `_exportTsq` stores the nonce it generated; `_importTsr` calls the existing `timeStampEchoesNonce` and refuses a token that does not echo it. - One new l10n string (a nonce mismatch is a different failure from an imprint mismatch and deserves its own sentence), so 31 translations. - Touches the file format, so a short design note comes first. Explicitly NOT in scope: CMS signature and certificate-chain verification of the token. That reasoning is recorded in `rfc3161_timestamp.dart` and SECURITY_DESIGN §9 and still holds — X.509 path validation means a new dependency plus a bundled trust-anchor list that ages by definition, in an application that makes no network connection and promises tamper-evidence, not tamper-proofing. Split out of #516 so that issue can close once its remaining items are done.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#563
No description provided.