Internet-Draft Crypto-Agility Manifest October 2026
Acosta Expires 16 April 2027 [Page]
Workgroup:
Network Working Group
Internet-Draft:
draft-acosta-crypto-agility-manifest-02
Published:
Intended Status:
Informational
Expires:
Author:
L. Acosta
QuantaKrypto

A Well-Known Crypto-Agility Manifest

Abstract

This document defines a small JSON discovery manifest for cryptographic migration assessment. It distinguishes declarations, runtime observations and consumer verification, and separates key establishment from authentication. It covers heterogeneous endpoint profiles and evidence references. It does not define cryptographic negotiation, an attestation format, a scoring system, or authority to modify systems.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 16 April 2027.

▲

Table of Contents

1. Introduction

Cryptographic migration decisions need discoverable information about a specific system. A public manifest supplies declarations and evidence references; it cannot establish that every client, device or network path uses the declared algorithms. This individual proposal has no IETF consensus and does not claim universal post-quantum security.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

2. Discovery and Versioning

A producer publishes the manifest at /.well-known/crypto-agility.json on an HTTPS origin, using application/json [RFC8615] [RFC9110]. An origin is a scheme, host and port tuple [RFC6454]. This profile uses port 443 and DNS hostnames. Consumers MUST authenticate the HTTPS server and MUST NOT follow redirects automatically. Publication by an origin establishes only who served the declaration.

The relying party MUST configure the expected subject independently. For subject.kind origin, subject.id MUST equal the configured HTTPS origin serialized under [RFC6454]. Other kinds require an independently configured mapping from the discovery origin to the exact subject.id. Consumers MUST NOT infer authority over sibling hosts, repositories, fleets or deployment environments from a shared publisher.

The contract identifier is the JSON integer version value 2. Producers serve one representation at the discovery location; consumers MUST reject unsupported versions rather than reinterpret their fields. Any adapter for a separately supported source format MUST retain its evidence provenance and MUST NOT promote a source declaration or score into a runtime observation. There is no downgrade or content-negotiation protocol in this document.

Producers SHOULD supply ETag or Last-Modified validators and Cache-Control. Consumers SHOULD use conditional GET under [RFC9110] and [RFC9111], honor no-store and revalidation directives, and impose a local maximum cache age. A 304 response reuses bytes but MUST NOT extend manifest, evidence or observation validity. HTTP errors and unavailable manifests yield unknown posture, never unsupported cryptography.

Optional external change feeds MAY trigger a bounded refresh of the configured discovery origin. This document defines no feed URL, event schema, signing scheme or hash chain. Notifications MUST NOT replace snapshot validation, authorize execution, or redirect evidence fetching. Polling with backoff remains a recovery mechanism.

3. Data Model

The JSON object MUST conform to the schema in Appendix A, using JSON Schema 2020-12 [JSONSCHEMA] [JSONVALIDATION]. Strings are case-sensitive. Unknown properties and duplicate JSON member names MUST be rejected. Producers MUST use UTF-8 [RFC8259]. Documents MUST NOT exceed 1048576 octets or 16 nested containers. Each array has at most 256 entries, except profiles, which has at most 64; strings have at most 2048 Unicode code points unless the schema sets a stricter bound.

Timestamps use a restricted [RFC3339] form: uppercase T and Z, UTC, zero through six fractional-second digits, and no leap-second value. Consumers MUST validate calendar values and reject expiresAt less than or equal to generatedAt. They MUST NOT treat expired data as current. A local clock-skew allowance MAY be used; the reference consumer permits at most 300 seconds for future timestamps.

Every id MUST be unique within its collection. References in evidenceIds and profileIds MUST resolve within this manifest. Missing references, contradictory supported and unsupported values for one capability, and future observations MUST produce findings rather than a passing security decision.

The required version is the integer 2 and manifestType is crypto-agility. generatedAt identifies document generation and expiresAt its validity limit. Neither timestamp establishes when any endpoint was measured. subject contains required kind and id; optional environment and commit narrow descriptive context and do not prove deployed code.

observations is a required array, possibly empty. Each entry contains id, capability, value (supported, unsupported or unknown), method (declared, inferred or observed), observedAt and optional evidenceIds. For declared and inferred methods, observedAt is when the assertion was recorded. Capability names are descriptive identifiers; this document defines no global capability registry. Producers SHOULD use a protocol-specific registered algorithm identifier or an unambiguous implementation name where available.

evidence is an optional array. Each entry contains id, mediaType, digest and subjectId; uri is optional. subjectId MUST equal manifest subject.id. The digest object contains algorithm (sha-256, sha-384 or sha-512) and the exact lowercase hexadecimal value, respectively 64, 96 or 128 digits [RFC6234]. Hashing covers the complete evidence bytes before parsing or reserialization; HTTP content codings, if used, are removed first. Consumers MUST verify the digest before interpreting evidence. A digest match establishes byte integrity relative to the declaration, not authenticity.

profiles is a nonempty array of declared endpoint capability classes. Each contains id, endpointRole (client, server, peer or gateway), deviceClass, protocol, keyEstablishment, authentication and fallback (deny-classical, allow-classical or unknown). Empty algorithm arrays mean unspecified inventory, not demonstrated absence of support. Optional constraints are human-readable limitations; evidenceIds link supporting evidence. The schema lists device classes including browsers, mobile devices, servers, IoT, embedded and industrial devices.

migration is a required array, possibly empty. Each entry contains id, usage and status. Status values are unknown, planned, blocked, in-progress, validated and deployed. Optional algorithm, target, deadline, profileIds, evidenceIds and blockers describe the plan. A producer claiming validated or deployed MUST supply evidenceIds; the consumer MUST independently verify relevant validation or deployment evidence before relying on that claim.

policies and exceptions are optional descriptive records, not remotely granted policy authority. Policy entries contain id, scope, source and optional effectiveAt. Exception entries contain findingId, reason, expiresAt and optional owner. Consumers MUST NOT use a manifest-supplied policy or exception to suppress a security finding without separate local authorization; expired or unowned exceptions are not valid enforcement exceptions.

4. Observations and Verification

Declared means an operator assertion. Inferred means a tool derived a conclusion, for example from a source scan. Observed means a runtime measurement was performed and requires at least one evidence reference. This producer-supplied label is not evidence verification. Independently verified is a consumer result and is deliberately not a manifest method value.

Before accepting observed evidence, consumers MUST verify subject, scope, acquisition time, freshness and provenance against locally configured policy. They MUST impose a maximum measurement age even when the manifest is still fresh. The reference consumer uses 86400 seconds by default. Stale, unavailable, incomplete or conflicting evidence cannot establish current protection.

Consumers that accept signed evidence MUST use an existing signature or attestation format with a documented application profile. They MUST constrain algorithms, verify signatures with independently configured issuer keys, and validate issuer authorization, audience, purpose, subject and validity. Replay handling MUST bind accepted statement identifiers or freshness checkpoints to the issuer and subject in protected durable state. Loss of that state requires explicit recovery; a newly issued wrapper MUST NOT refresh an old measurement. [RFC8725] describes relevant JWT validation requirements. No signature format or mandatory signature algorithm is introduced here.

A trusted signature authenticates what an issuer asserted, not the truth or completeness of that assertion. Independent verification requires a relying party to evaluate measurement evidence or repeat the measurement through a trusted process. A consumer MUST report which of signature authenticity, evidence integrity, measurement validity and independent corroboration it actually checked.

For TLS 1.3 [RFC8446], a claim of hybrid key establishment MUST identify the negotiated group from a completed authenticated connection. An offered group, cipher-suite name or self-reported capability is insufficient. Certificate-chain validation, reference-identity matching and handshake authentication MUST succeed. The probe configuration, endpoint identity, time and group MUST be bound to the evidence. Authentication algorithms MUST be assessed separately: hybrid key establishment does not make an RSA or ECDSA certificate post-quantum secure.

A classical-only negotiation MUST be reported as classical. Testing a classical-only peer distinguishes permitted fallback from a deny-classical policy; it does not prove resistance to every active downgrade attack. Implementations MUST rely on protocol-native authenticated negotiation and MUST NOT construct hybrid cryptography from manifest fields.

The reference implementation accepts Ed25519 or ML-DSA-65 signatures under an explicit local key-algorithm policy. ML-DSA-65 JWS uses [RFC9964] with an empty context and pure ML-DSA, not HashML-DSA. Its public-key import follows [RFC9881]. An existing signing authority can issue this standard envelope without moving its private key. Successful signature verification does not verify the signed measurement.

5. Compatibility and Monitoring

Compatibility from profile intersection is only declared compatibility. A consumer MUST NOT infer interoperability from deviceClass alone. Empty inventories, unresolved firmware or resource constraints and untested authentication trust yield unknown. A definite protocol mismatch or absence of common declared algorithms can be reported as a declared mismatch. Real interoperability requires measurements on each relevant software, firmware and trust-store combination.

A gateway that terminates TLS creates separate hops. A successful browser-to-gateway test MUST NOT establish gateway-to-device protection. Offline or constrained devices SHOULD be represented through an authenticated fleet gateway with explicit connectivity constraints; missing telemetry is unknown. This document supplies no device enrollment protocol and no guarantee of inventory coverage.

Monitors SHOULD detect expired evidence, changed algorithms, classical fallback, missing profiles and invalid snapshots. They SHOULD preserve the last valid baseline when new input fails, distinguish failure from recovery, and emit actionable, deduplicated local alerts. State MUST be scoped to the subject and protected against unauthorized modification and rollback to the extent provided by the local platform. A manifest does not authorize a monitor to change firmware, keys, software or network policy.

6. Security and Privacy Considerations

All public content is untrusted, including signed content from a compromised issuer. Consumers MUST bound retrieval time, response bytes, parsing, evidence size and retries, and defend against server-side request forgery, DNS rebinding and unsafe redirects. Network destinations MUST be independently authorized. Public discovery MUST NOT automatically fetch private addresses, local file references or issuer-supplied keys. Locally provisioned evidence directories MAY be used by offline tools with path confinement.

URLs, descriptive strings and constraints MUST NOT be executed or interpreted as instructions. Public manifests SHOULD omit secrets, internal hostnames, device identifiers and detailed vulnerability inventories. Producers should assess the privacy impact of exposing migration gaps and change cadence. Consumers MUST NOT equate scores, declarations, signatures or successful sample measurements with comprehensive security or regulatory compliance.

7. IANA Considerations

This document proposes provisional registration of the following well-known URI under [RFC8615]. Registration is requested, not assumed to have been approved.

URI suffix: crypto-agility.json. Change controller: Leon Acosta (leon@quantakrypto.com). Specification document: this document, Sections 2 and 3. Status: provisional. Related information: HTTPS on port 443, DNS hostnames, application/json. No additional path components, query parameters or fragment identifiers are defined.

8. Normative References

[JSONSCHEMA]
JSON Schema, "JSON Schema: A Media Type for Describing JSON Documents", 2020-12, work in progress, , <https://json-schema.org/draft/2020-12/json-schema-core>.
[JSONVALIDATION]
JSON Schema, "JSON Schema Validation: A Vocabulary for Structural Validation of JSON", 2020-12, work in progress, , <https://json-schema.org/draft/2020-12/json-schema-validation>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC3339]
Newman, G. K. A. C., "Date and Time on the Internet: Timestamps", RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/info/rfc3339>.
[RFC6234]
Hansen, D. E. 3. A. T., "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, , <https://www.rfc-editor.org/info/rfc6234>.
[RFC6454]
Barth, A., "The Web Origin Concept", RFC 6454, DOI 10.17487/RFC6454, , <https://www.rfc-editor.org/info/rfc6454>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC8259]
Bray, T., "The JavaScript Object Notation (JSON) Data Interchange Format", RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/info/rfc8259>.
[RFC8615]
Nottingham, M., "Well-Known Uniform Resource Identifiers (URIs)", RFC 8615, DOI 10.17487/RFC8615, , <https://www.rfc-editor.org/info/rfc8615>.
[RFC9110]
Reschke, R. F. M. N. A. J., "HTTP Semantics", RFC 9110, DOI 10.17487/RFC9110, , <https://www.rfc-editor.org/info/rfc9110>.
[RFC9111]
Reschke, R. F. M. N. A. J., "HTTP Caching", RFC 9111, DOI 10.17487/RFC9111, , <https://www.rfc-editor.org/info/rfc9111>.

9. Informative References

[RFC8446]
Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, , <https://www.rfc-editor.org/info/rfc8446>.
[RFC8725]
Jones, Y. S. D. H. A. M., "JSON Web Token Best Current Practices", RFC 8725, , <https://www.rfc-editor.org/info/rfc8725>.
[RFC9881]
Westerbaan, J. M. P. K. S. T. A. B. E., "Internet X.509 Public Key Infrastructure -- Algorithm Identifiers for the Module-Lattice-Based Digital Signature Algorithm (ML-DSA)", RFC 9881, DOI 10.17487/RFC9881, , <https://www.rfc-editor.org/info/rfc9881>.
[RFC9964]
Steele, M. P. A. O., "ML-DSA for JSON Object Signing and Encryption (JOSE) and CBOR Object Signing and Encryption (COSE)", RFC 9964, DOI 10.17487/RFC9964, , <https://www.rfc-editor.org/info/rfc9964>.

Appendix A. JSON Schema

This schema is normative. Cross-reference resolution, time ordering, uniqueness of record identifiers, subject binding and evidence verification also require the semantic checks specified above. The schema is bundled; validators MUST NOT fetch schemas selected by an untrusted manifest.

{
  "$schema":"https://json-schema.org/draft/2020-12/schema",
  "title":"Crypto-Agility Manifest version 2",
  "type":"object",
  "additionalProperties":false,
  "required":
  [
    "version",
    "manifestType",
    "generatedAt",
    "expiresAt",
    "subject",
    "observations",
    "migration",
    "profiles"
  ],
  "properties":
  {
    "version":{"const":2},
    "manifestType":{"const":"crypto-agility"},
    "generatedAt":
    {
      "type":"string",
      "format":"date-time",
      "minLength":1,
      "maxLength":2048,
      "pattern":
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:[0-5]\\d(?:\\.\\d{1,6})?Z$"
    },
    "expiresAt":
    {
      "type":"string",
      "format":"date-time",
      "minLength":1,
      "maxLength":2048,
      "pattern":
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:[0-5]\\d(?:\\.\\d{1,6})?Z$"
    },
    "subject":
    {
      "type":"object",
      "additionalProperties":false,
      "required":["kind","id"],
      "properties":
      {
        "kind":
        {
          "enum":
          [
            "origin",
            "service",
            "repository",
            "artifact",
            "device-fleet"
          ]
        },
        "id":{"type":"string","minLength":1,"maxLength":2048},
        "environment":
        {"type":"string","minLength":1,"maxLength":2048},
        "commit":{"type":"string","minLength":1,"maxLength":2048}
      }
    },
    "observations":
    {
      "type":"array",
      "items":
      {
        "type":"object",
        "additionalProperties":false,
        "required":["id","capability","value","method","observedAt"],
        "properties":
        {
          "id":{"type":"string","minLength":1,"maxLength":2048},
          "capability":
          {"type":"string","minLength":1,"maxLength":2048},
          "value":{"enum":["supported","unsupported","unknown"]},
          "method":{"enum":["observed","inferred","declared"]},
          "observedAt":
          {
            "type":"string",
            "format":"date-time",
            "minLength":1,
            "maxLength":2048,
            "pattern":
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:[0-5]\\d(?:\\.\\d{1,6})?Z$"
          },
          "evidenceIds":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256,
            "uniqueItems":true
          }
        }
      },
      "maxItems":256
    },
    "evidence":
    {
      "type":"array",
      "items":
      {
        "type":"object",
        "additionalProperties":false,
        "required":["id","mediaType","digest","subjectId"],
        "properties":
        {
          "id":{"type":"string","minLength":1,"maxLength":2048},
          "uri":
          {
            "type":"string",
            "format":"uri",
            "minLength":1,
            "maxLength":2048
          },
          "mediaType":
          {"type":"string","minLength":1,"maxLength":2048},
          "digest":
          {
            "type":"object",
            "additionalProperties":false,
            "required":["algorithm","value"],
            "properties":
            {
              "algorithm":{"enum":["sha-256","sha-384","sha-512"]},
              "value":
              {
                "type":"string",
                "pattern":"^[0-9a-f]+$",
                "minLength":1,
                "maxLength":2048
              }
            },
            "allOf":
            [
              {
                "if":
                {"properties":{"algorithm":{"const":"sha-256"}}},
                "then":
                {
                  "properties":
                  {"value":{"minLength":64,"maxLength":64}}
                }
              },
              {
                "if":
                {"properties":{"algorithm":{"const":"sha-384"}}},
                "then":
                {
                  "properties":
                  {"value":{"minLength":96,"maxLength":96}}
                }
              },
              {
                "if":
                {"properties":{"algorithm":{"const":"sha-512"}}},
                "then":
                {
                  "properties":
                  {"value":{"minLength":128,"maxLength":128}}
                }
              }
            ]
          },
          "subjectId":
          {"type":"string","minLength":1,"maxLength":2048}
        }
      },
      "maxItems":256
    },
    "migration":
    {
      "type":"array",
      "items":
      {
        "type":"object",
        "additionalProperties":false,
        "required":["id","usage","status"],
        "properties":
        {
          "id":{"type":"string","minLength":1,"maxLength":2048},
          "usage":
          {
            "enum":
            [
              "key-establishment",
              "authentication",
              "signature",
              "encryption",
              "other"
            ]
          },
          "algorithm":
          {"type":"string","minLength":1,"maxLength":2048},
          "target":{"type":"string","minLength":1,"maxLength":2048},
          "status":
          {
            "enum":
            [
              "unknown",
              "planned",
              "blocked",
              "in-progress",
              "validated",
              "deployed"
            ]
          },
          "deadline":
          {
            "type":"string",
            "format":"date-time",
            "minLength":1,
            "maxLength":2048,
            "pattern":
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:[0-5]\\d(?:\\.\\d{1,6})?Z$"
          },
          "profileIds":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256,
            "uniqueItems":true
          },
          "evidenceIds":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256,
            "uniqueItems":true
          },
          "blockers":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256
          }
        }
      },
      "maxItems":256
    },
    "profiles":
    {
      "type":"array",
      "minItems":1,
      "items":
      {
        "type":"object",
        "additionalProperties":false,
        "required":
        [
          "id",
          "endpointRole",
          "deviceClass",
          "protocol",
          "keyEstablishment",
          "authentication",
          "fallback"
        ],
        "properties":
        {
          "id":{"type":"string","minLength":1,"maxLength":2048},
          "endpointRole":
          {"enum":["client","server","peer","gateway"]},
          "deviceClass":
          {
            "enum":
            [
              "browser",
              "mobile",
              "desktop",
              "server",
              "iot",
              "embedded",
              "industrial",
              "network",
              "other"
            ]
          },
          "protocol":
          {"type":"string","minLength":1,"maxLength":2048},
          "keyEstablishment":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256,
            "uniqueItems":true
          },
          "authentication":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256,
            "uniqueItems":true
          },
          "fallback":
          {"enum":["deny-classical","allow-classical","unknown"]},
          "constraints":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256
          },
          "evidenceIds":
          {
            "type":"array",
            "items":{"type":"string","minLength":1,"maxLength":2048},
            "maxItems":256,
            "uniqueItems":true
          }
        }
      },
      "maxItems":64
    },
    "policies":
    {
      "type":"array",
      "items":
      {
        "type":"object",
        "required":["id","scope","source"],
        "properties":
        {
          "id":{"type":"string","minLength":1,"maxLength":2048},
          "scope":{"type":"string","minLength":1,"maxLength":2048},
          "source":{"type":"string","minLength":1,"maxLength":2048},
          "effectiveAt":
          {
            "type":"string",
            "format":"date-time",
            "minLength":1,
            "maxLength":2048,
            "pattern":
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:[0-5]\\d(?:\\.\\d{1,6})?Z$"
          }
        },
        "additionalProperties":false
      },
      "maxItems":256
    },
    "exceptions":
    {
      "type":"array",
      "items":
      {
        "type":"object",
        "required":["findingId","reason","expiresAt"],
        "properties":
        {
          "findingId":
          {"type":"string","minLength":1,"maxLength":2048},
          "reason":{"type":"string","minLength":1,"maxLength":2048},
          "owner":{"type":"string","minLength":1,"maxLength":2048},
          "expiresAt":
          {
            "type":"string",
            "format":"date-time",
            "minLength":1,
            "maxLength":2048,
            "pattern":
"^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:[0-5]\\d(?:\\.\\d{1,6})?Z$"
          }
        },
        "additionalProperties":false
      },
      "maxItems":256
    }
  },
  "$id":
  "https://quantakrypto.com/schema/crypto-agility-v2.schema.json"
}

Appendix B. Minimal Example

This example has no runtime measurements. Its profile is a declaration, not demonstrated compatibility or security.

{
  "version": 2,
  "manifestType": "crypto-agility",
  "generatedAt": "2026-10-11T10:00:00Z",
  "expiresAt": "2026-10-12T10:00:00Z",
  "subject": {
    "kind": "origin",
    "id": "https://example.org"
  },
  "observations": [],
  "migration": [],
  "profiles": [
    {
      "id": "service",
      "endpointRole": "server",
      "deviceClass": "server",
      "protocol": "TLS 1.3",
      "keyEstablishment": [],
      "authentication": [],
      "fallback": "unknown"
    }
  ]
}

Author's Address

Leon Acosta
QuantaKrypto