# Open Print threat model

This document says what Open Print is trying to protect, what a verifier has to
trust, and where the protection ends. It covers the `1.0.0` record formats and
reference implementation.

## The short version

Open Print detects changes to signed edition records and attributes those
records to a key in a supplied issuer record. It can also detect rewritten
registry history when the verifier retains a trusted checkpoint.

It cannot establish that an issuer's real-world identity is true, stop an
artwork from being copied, recover a stolen signing key, provide a trusted
clock, or decide who legally owns a work.

## Assets and security goals

The system protects five related things:

1. Certificate claims should not change without invalidating their digest and
   issuer signature.
2. A certificate ID and edition sequence should be issued at most once in one
   trusted registry history.
3. Cancellation and replacement should be later signed events, never silent
   edits to issuance.
4. A remembered checkpoint should expose a shorter registry or a conflicting
   branch.
5. An archive should be complete enough to verify without the issuing service.

Public collector display names are optional. Private collector labels and
signing keys are not Open Print records and must never enter a public archive.

## Trust anchors

A verifier supplies the issuer record used to trust a public key. The verifier
is responsible for obtaining that issuer record through an authentic route. If
an attacker can replace both a certificate and the issuer record on first use,
the signatures alone cannot reveal the substitution.

A saved checkpoint is the trust anchor for rollback and fork detection. A
checkpoint fetched from the same compromised service at the same time as the
registry is only a consistency check; it is not an independent observation.
Institutions should retain checkpoints in another system or publish them
through more than one channel.

Verification also trusts the local runtime's SHA-256, Ed25519, random-number,
UTF-8, JSON, and filesystem implementations, plus the exact Open Print code
being executed. Release checksums and attestations help connect packaged code
to its source, but do not prove that the source is free of bugs.

## Adversaries considered

Open Print expects that an attacker may:

- edit, remove, reorder, duplicate, or replay stored JSON records;
- recompute ordinary SHA-256 digests after editing unsigned data;
- substitute an issuer record or public key;
- present an older registry or different histories to different people;
- send malformed, deeply nested, oversized, or deliberately confusing JSON;
- copy a certificate or artwork file byte for byte;
- operate the service that stores otherwise valid public records;
- obtain a retired or active private key.

The model does not assume the hosting service is honest. It does assume that a
verifier has at least one authentic issuer record and, for history comparison,
an earlier authentic checkpoint.

## Controls and remaining risk

| Attack | Control | Remaining risk |
| --- | --- | --- |
| Edit certificate claims | Canonical JSON, SHA-256, and Ed25519 over claims, integrity, and signature metadata | A holder of the issuer private key can sign new claims. |
| Rewrite signature time or key ID | Algorithm, key ID, creation time, and scope are included in the signed input | A signer can choose a false time when creating a new signature; Open Print has no trusted clock. |
| Use multiple base64 spellings | Decoders accept only canonical unpadded base64url | Other implementations must enforce the same rule. |
| Publish a weak Ed25519 point | Issuer validation and key import reject every small-order encoding, including alternate sign-bit forms | Other implementations must apply an equivalent group-membership boundary. |
| Reorder or delete registry events | Every event includes the previous event digest | A service can truncate the end unless the verifier remembers a later checkpoint. |
| Forge a cancellation | Registry verification binds terminal events and replacements to the original issuance issuer | A compromised original issuer key can make a valid cancellation. |
| Reuse an edition sequence | Registry and archive verification bind all issuance metadata and reject repeated certificate IDs and edition/sequence pairs | Separate registry forks can each look unique until retained checkpoints are compared. |
| Replace an issuer record | The verifier chooses its issuer trust anchor | First-use distribution remains an application and institutional problem. |
| Leak private JWK fields through an issuer record | The issuer schema accepts one exact Ed25519 public JWK shape and rejects every extra field | Applications must still keep private-key objects away from logging and serialization code. |
| Steal a private key | Revoked keys are distrusted for their complete history | Open Print cannot identify which signatures preceded the theft. |
| Recompute an archive digest | Archives verify every nested signature, registry link, and checkpoint | The archive digest itself provides integrity, not issuer authentication. |
| Send oversized JSON to a CLI | Verification CLIs reject files above 64 MiB before parsing | Library callers receiving in-memory values must enforce limits appropriate to their service. |
| Race local issuance | The Node file store uses one lock and atomic replacement on one filesystem; it never deletes a lock merely because it looks old | An orphaned lock requires operator recovery. The store is not a distributed lock or shared multi-server database. |
| Substitute release tooling | Privileged workflows pin external actions to reviewed commit SHAs and package tests exclude the public fixture signer | Upstream action changes require an explicit reviewed pin update. Human review is still required before publication. |

## Cryptographic boundaries

Certificates sign the canonical object `{ claims, integrity, signature }`,
where `signature` contains every signature field except `value`. Registry events
and checkpoints use `{ payload, integrity, signature }` with the same exclusion.
The signed payload always contains its schema identifier and schema version,
which separates the record types.

Certificate fingerprints identify the signed claims digest, not the artwork
bytes, signature value, collector account, or legal owner. Two copies of one
certificate therefore have the same fingerprint by design.

Open Print fixes SHA-256, Ed25519, and `open-print-c14n-1` for the 1.x format.
Replacing an algorithm or changing the signed input requires a new record
version. Algorithm agility is a future migration problem, not an optional
field in a v1 record.

## Time and key lifecycle

Validity windows are evaluated against the signed signature creation time.
That time is tamper-evident after the signature is made, but it is asserted by
the signer and is not independently timestamped. A malicious key holder can
backdate a new record.

For that reason, revocation is deliberately stronger than expiration. A
revoked key is not trusted at any date. A retired key remains useful for old
signatures inside its validity window, so institutions must protect or destroy
the retired private half according to their own policy.

## Availability and resource limits

The schemas put portable bounds on integer values and the public collector
label. They do not impose one universal size on registries or archives because
institutional collections vary widely. The included CLIs use a 64 MiB JSON
file limit. Servers should add request limits, nesting limits, timeouts, and
rate limits before calling the in-memory APIs.

Open Print does not promise availability. Git mirrors, offline archives, and
independently retained checkpoints are the recovery strategy.

## Out of scope

The following are not security properties of Open Print:

- preventing copying, screenshots, printing, or redistribution;
- proving authorship, copyright, possession, legal ownership, or value;
- verifying a person's or institution's real-world identity;
- keeping public records confidential;
- processing payments or managing accounts;
- securing a host, browser, database, CDN, or gallery network;
- protecting a private key exposed to client-side code or committed to Git.

The project also permanently excludes blockchains, cryptocurrency, wallets,
tokens, NFTs, gas fees, and distributed ledgers.

## Keeping this model current

Any change to a schema, signed input, key rule, registry transition, archive
relationship, storage adapter, or release path must update this document and
the security test suite. Review instructions and finding records live in
`SECURITY_REVIEW.md`.
