Skip to content

OSAP Envelope

Status: See Status of This Document.

This document normatively defines the OSAP attestation envelope: its structure, identifier format, versioning, canonicalization, and signing procedure. The machine-readable form is osap-envelope.schema.json; field-by-field definitions are in data-model.md § 3.

1. Semantics

A valid envelope signature establishes that a specific issuer signed a fingerprint of a specific asset at a specific time and included a specific claim. It does not establish that the claim is true.

2. Structure

An envelope is a single JSON object. Required members: osap, id, type, issuer, issued_at, proof. Optional members: subject, claims, valid_from, valid_until, derived_from, corrects, revokes, evidence, revocation.

  • Envelopes MUST validate against osap-envelope.schema.json.
  • Envelopes MUST NOT contain members not defined by the schema (additionalProperties: false).
  • type MUST be one of the five attestation types defined in claims.md: SourceAttestation, DerivativeAttestation, CorrectionAttestation, RevocationAttestation, ContextAttestation.
  • issuer.key_id MUST equal proof.verificationMethod.
  • For all types except RevocationAttestation, the envelope SHOULD contain a subject with at least one asset_hashes entry. A RevocationAttestation MAY omit subject because it targets an attestation (via revokes), not an asset.
  • Issuers SHOULD include the revocation.status_url member so verifiers can find the issuer's revocation list without extra discovery.

A complete example is ../examples/source-attestation.json.

3. Identifier

The id member is a stable identifier for the attestation.

  • For attestations whose subject contains an exact-bytes SHA-256 fingerprint, the id SHOULD be:
text
osap:attestation:sha256:<hex>

where <hex> is the lowercase hexadecimal value of the primary asset hash — the first entry in subject.asset_hashes.

  • id MUST be non-empty and MUST be stable: once published, an attestation's id never changes. A changed asset produces a new fingerprint and therefore a new attestation with a new id.
  • Because two issuers can attest the same asset, id alone is not globally unique; the pair (issuer.id, id) is the practical uniqueness scope in v0.1.

Note (non-normative): a RevocationAttestation has no subject asset; issuers assign it an id in the same format derived from a hash of their choosing (for example, the exact-bytes hash of a related document), or any other stable non-empty string. The format constraint on id is a SHOULD, not a MUST, precisely for cases like this.

4. Versioning

  • Every envelope MUST carry "osap": "0.1".
  • Verifiers MUST reject documents whose osap value they do not support, using the schema-validation failure path of verification.md.
  • v0.1 is an experimental draft: future versions MAY introduce breaking changes and are NOT REQUIRED to be backward compatible.

5. Temporal Fields

  • issued_at (REQUIRED) is the issuer's statement of when the attestation was issued. It is an assertion by the issuer, not a proven timestamp. Independent chronology evidence is the role of transparency logs (transparency-logs.md, extension area).
  • valid_from / valid_until (OPTIONAL) delimit the attestation's stated validity. Verifiers MUST NOT treat an attestation examined outside this window as invalid evidence; they MUST report the window status distinctly (see verification.md). A signature made during the validity window remains historically verifiable afterward (see security-considerations.md).
  • proof.created records when the proof was made and MAY differ slightly from issued_at.

6. Canonicalization and Signing

v0.1 defines exactly one proof mechanism: Ed25519 over the JSON Canonicalization Scheme (JCS, RFC 8785), expressed as a Data Integrity style proof object with cryptosuite eddsa-jcs-2026.

6.1 Signing procedure

Given a complete envelope (all members present except the signature value), the issuer MUST:

  1. Construct the envelope JSON object, including the proof object with type, cryptosuite, created, verificationMethod, and proofPurpose populated, and without the proofValue member.
  2. Canonicalize the entire object using JCS (RFC 8785).
  3. Encode the canonical form as UTF-8 bytes. These bytes are the signing input.
  4. Sign the signing input with the Ed25519 private key corresponding to proof.verificationMethod, producing a raw 64-byte signature.
  5. Encode the signature as unpadded base64url (RFC 4648 § 5, no = padding) and set it as proof.proofValue.

The final document is the envelope with proofValue present. Verification re-canonicalizes the document, so published whitespace and member ordering do not affect verification.

6.2 Verification procedure

Given an envelope, a verifier MUST:

  1. Remove the proofValue member from the proof object (leave all other proof members in place).
  2. Canonicalize the resulting object using JCS and encode as UTF-8 bytes.
  3. Decode proofValue from unpadded base64url into a 64-byte signature. If decoding fails or the length is not 64 bytes, signature verification fails.
  4. Resolve proof.verificationMethod to an Ed25519 public key via issuer metadata (identity.md).
  5. Verify the Ed25519 signature over the bytes from step 2.

This is one step within the full algorithm in verification.md, which also defines key-validity, revocation, and trust-bundle evaluation.

6.3 Proof object

MemberValue in v0.1
type"DataIntegrityProof"
cryptosuite"eddsa-jcs-2026"
createdRFC 3339 date-time
verificationMethodkey identifier, e.g. did:web:publisher.example#key-2026
proofPurpose"assertionMethod"
proofValueunpadded base64url of the raw 64-byte Ed25519 signature

Verifiers MUST reject proofs whose type, cryptosuite, or proofPurpose differ from these values. Additional cryptosuites (including post-quantum signatures) are a future extension area.

Note (non-normative): the same proof structure and signing procedure apply to trust bundles (trust-bundles.md) and, when signed, revocation lists (data-model.md § 6).

7. Canonicalization Requirements

  • Implementations MUST use JCS (RFC 8785) exactly. Ad hoc sorted-key serializers can produce different number formatting or string escaping. See security-considerations.md.
  • Because JCS requires deterministic number serialization, issuers SHOULD avoid non-integer numbers in claim values where a string representation is equally expressive.
  • The signing input is computed over the entire document minus proofValue. Any modification to any member — including reordering array elements — invalidates the signature.