Internet-Draft OASNT-CAID August 2026
Thallapelly Expires 6 February 2027 [Page]
Workgroup:
Network Working Group
Internet-Draft:
draft-thallapelly-oasnt-caid-01
Published:
Intended Status:
Standards Track
Expires:
Author:
A. Thallapelly
OmniArx

OASNT-CAID: Canonical Action Identifier Derivation and the Named-Human Binding

Abstract

This document profiles OASNT tokens for consumption by executor-side processing models. It fixes one normative derivation of a Canonical Action Identifier (CAID) from the OASNT action digest, so that every executor checks the same derivation rather than each integration defining its own, and it specifies the semantics of the token's named-human binding, including a subject-to-enrollment check whose absence this profile makes a refusal.

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 6 February 2027.

Table of Contents

1. Introduction

[I-D.thallapelly-oasnt] (hereafter "the core document") defines the OASNT token: a compact JWS in which a hardware-bound device key attests that a specific human authorized one specific action, with the disclosure the human was shown bound into the signature. The core document deliberately stops at the token. It does not define how an executor, having decided to admit evidence of several kinds, identifies the action that evidence authorizes.

Executor-side processing models such as [I-D.schrock-action-evidence-boundary] work in terms of a Canonical Action Identifier: a value the executor derives for the effect it is about to perform and matches against the identifiers derived from admissible evidence. Left unspecified, that derivation would be reinvented by every executor-to-OASNT integration, and two integrations that disagreed on any detail would disagree silently.

This document fixes the derivation once. It also specifies the named-human binding of the token: what a validated token asserts about the human it names, the subject-to-enrollment check a verifier is required to make, and what the binding deliberately does not assert.

This profile is written from a running implementation. The subject verification requirement in Section 5 exists because implementing this profile exposed its absence; see Section 6.3.

2. Conventions and Definitions

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.

"The core document" refers to [I-D.thallapelly-oasnt]. "Action", "canonical action", "disclosure", and the claim names adg, dsp, rqf, sub, and cnf have the meanings the core document gives them.

"Effect" refers to the concrete operation an executor is about to perform, in the executor's own representation.

3. The Canonical Action Identifier

3.1. Syntax

caid          = "oasnt:caid:" version ":" digest
version       = 1*DIGIT
digest        = 43base64url-char
base64url-char = ALPHA / DIGIT / "-" / "_"

A CAID is an opaque octet string. It is not a URI under [RFC3986], it MUST NOT be dereferenced, and no registration of the leading literal is requested or implied. A CAID identifies an action within OASNT; Section 6.4 states the consequence for executors that also hold evidence under other profiles.

This document defines version 1.

3.2. Derivation

For an action with type T and parameters P, the version 1 CAID is:

CAID(T, P) = "oasnt:caid:1:" || BASE64URL(SHA-256(canonical-action(T, P)))

where canonical-action is the canonical action encoding of the core document, under its escaping rules and its UTF-8-octet key ordering; SHA-256 is [RFC6234]; and BASE64URL is the URL-safe alphabet of [RFC4648] without padding, yielding exactly 43 characters.

The digest octets are, by construction, identical to the value of the adg claim of an OASNT token minted for the same action. A conforming derivation therefore has two equivalent forms:

  • Recomputed. Derive from a representation of the action the deriving party itself holds, by computing the canonical action encoding and its digest. This is the form an executor uses for its effect, and the form a verifier that recomputed adg during token validation uses for the evidence.

  • Carried. Prefix the adg value of a validated token. This form is only meaningful after the token's signature has verified under an enrolled key, and it carries only the strength of that signature: it proves what the device signed, not what the executor is about to do. A carried value that is not exactly 43 characters of the base64url alphabet MUST be refused rather than prefixed.

Every CAID comparison in Section 4 is an octet-string equality. Nothing is ever parsed out of a CAID.

3.3. Versioning

Version 1 pins the canonicalization rules of the core document as of this writing: the escaping of structural delimiters and the UTF-8-octet key ordering. Any change to those rules is a new version, never a silent change under the same one.

Because the version participates in the octet-string comparison, identifiers derived under different versions never compare equal. A version mismatch therefore manifests as an ordinary CAID mismatch and fails closed. No version negotiation exists or is needed.

4. CAID Matching

An executor admitting an OASNT token as evidence for an effect MUST proceed as follows.

  1. Validate the token as the core document's verification procedure requires, with the single-use boundary of Section 4.1 observed: the executor MUST establish that the core document's replay condition is satisfiable, that jti is present and has not been seen, without yet recording it as seen. A token that fails validation yields no CAID and no further processing.

  2. Derive CAID-effect from the executor's own representation of the effect it is about to perform, using the recomputed form of Section 3.2. The executor MUST NOT construct CAID-effect from any value carried in the token or supplied by the party presenting it.

  3. Derive CAID-evidence from the validated token: the recomputed form where the validator recomputed adg against an expected action, the carried form otherwise.

  4. The evidence identifies the effect only if CAID-effect and CAID-evidence are equal as octet strings. Any other outcome, including a refused carried derivation in step 3, MUST be treated as a refusal (caid-mismatch) and MUST NOT be downgraded to a warning.

Note that step 2 makes the comparison self-strengthening: equality between a self-derived CAID-effect and a carried-basis CAID-evidence is itself a recomputation of the token's adg against the executor's view of the effect. The carried basis is weak only where matching does not happen, for example when a CAID is stored or forwarded for audit without being compared; such a value retains only signature strength and MUST be marked as carried wherever that distinction is visible.

4.1. Single-use and the matching boundary

The core document requires that jti be present and not have been seen before. That condition is checked during step 1, but the token's single use MUST NOT be recorded as spent until the comparison of step 4 has succeeded and the executor is committed to performing the effect.

Consuming earlier is a defect with a specific shape. An executor that spends jti while validating, and then refuses caid-mismatch at step 4, has destroyed a valid authorization for an effect that never occurred. The approver's evidence is gone, the effect did not happen, and the only remedy is a fresh human approval. A party able to induce a mismatch, by presenting the token against a near-miss effect, can therefore burn authorizations at will, converting an integrity refusal into a denial of service against the human in the loop.

Executors MUST therefore evaluate validity and policy sufficiency separately from consumption, and MUST release any provisional reservation when a refusal is returned for any reason, including caid-mismatch. The practical shape is a reservation taken atomically before verification and either committed on full acceptance or released on refusal; this profile does not require that mechanism, only the property. A refusal MUST NOT consume.

This applies to every refusal reachable after step 1, not only caid-mismatch, and it composes with the group semantics of the enforcement profile: a refused token likewise leaves its group unconsumed.

5. The Named-Human Binding

5.1. What a validated token asserts

The core document records, at enrollment, a subject identifier bound to the enrolled key, and requires the sub claim in every token. This profile makes the linkage load-bearing. A token validated under this profile asserts:

the subject recorded at enrollment and named by sub, in control of the enrolled hardware-bound key identified by cnf.jkt, approved the specific action identified by the CAID, having been shown the disclosure whose digest dsp carries, on a device whose runtime integrity was assessed as the int claim reports.

5.2. Subject verification

A verifier operating under this profile MUST refuse a token (sub-mismatch) when sub is absent, is not a string, or is not equal to the subject identifier recorded at enrollment for the key that verified the signature.

This check is REQUIRED. Without it, a token signed by one enrolled key may assert any subject whatsoever: every cryptographic check passes, the key is authorized, and the named human is fiction. Section 6.3 records the implementation experience behind this requirement.

5.3. What the binding does not assert

The binding deliberately asserts nothing beyond the statement above. In particular:

  • It is not a per-signature user-verification ceremony. The approval step precedes the signature; no claim attests a biometric or knowledge-factor ceremony for each individual signature. A relying party that requires per-signature user verification composes it alongside this profile; this profile will not fold it into the core semantics.

  • It does not assert comprehension or legal consent. A valid dsp proves which octets were displayed and signed, not that they were understood. This limit is inherited from the core document unchanged.

  • It does not strengthen the int claim. A device-asserted integrity verdict retains exactly the limits the core document states.

6. Security Considerations

6.1. One derivation or none

The interoperability property this profile buys is deliberately fragile in one direction: two implementations that disagree on any canonicalization detail, escaping, ordering, or version, produce disjoint CAID spaces and refuse each other's identifiers. The failure mode of divergence is caid-mismatch, which denies. Nothing about the construction can turn a divergence into an acceptance.

6.2. Carried derivations

The carried form of Section 3.2 is a convenience for parties that cannot recompute, and it is exactly as strong as the signature over the token that carried it. The matching procedure of Section 4 restores recomputation strength wherever it is actually applied. Deployments SHOULD treat an unmatched carried CAID, for example in logs or forwarded evidence, as a claim by the device rather than a fact about any effect.

6.3. The subject check

The reference implementation, prior to this profile, validated enrollment, signature, thumbprint, freshness, replay, all three bindings, and the integrity claim, and did not compare sub against the enrollment record. A token signed by an enrolled key claiming a different subject passed every check. The defect was found while implementing this profile's named-human semantics, was fixed by the refusal Section 5.2 requires, and is now exercised by a published refusal vector (the named-human substitution case in the implementation's adversarial corpus, and Appendix A).

The lesson generalizes: the named-human binding is precisely as strong as the weakest link between sub, the enrollment record, and the key. A deployment that enrolls keys without recording a verified subject identifier has nothing for this check to bind, and the assertion of Section 5 silently degrades to "some enrolled key approved this". Enrollment procedures SHOULD therefore verify the subject identifier they record.

6.4. Namespace separation

The fixed leading literal exists so that an OASNT-derived identifier can never be confused with an identifier derived by another evidence profile that also feeds an executor. Executors handling multiple evidence profiles SHOULD treat the full octet string, prefix included, as the identifier and compare nothing shorter.

The consequence is worth stating plainly: a CAID under this profile identifies an action within OASNT, and it is not a join key across evidence profiles. Another profile that derives its identifier over a different preimage of the same logical action produces a different digest under a different prefix, and no octet-string comparison between the two ever succeeds, by design and fail-closed. An executor holding an OASNT token and a non-OASNT authorization record for the same action therefore cannot join them by comparing identifiers. It derives an identifier under each profile separately, from its own representation of the effect, and joins on that representation.

This document defines an OASNT-specific derivation and namespace. The term Canonical Action Identifier originates in executor-side processing models ([I-D.schrock-action-evidence-boundary]), and a general CAID framework with its own action object, canonicalization, and identifier syntax is defined in [I-D.schrock-canonical-action-identifier]. Identifiers derived under this document are not wire-compatible with identifiers derived under that framework and never compare equal to them; the two coexist by the same rule this section states for evidence profiles generally.

7. IANA Considerations

This document has no IANA actions. The literal oasnt:caid: is a fixed string defined by this document; it is not a URI scheme, not a URN namespace, and no registration is requested.

8. References

8.1. Normative References

[I-D.thallapelly-oasnt]
Thallapelly, A., "OASNT: Attested Action Authorization Tokens", Work in Progress, Internet-Draft, draft-thallapelly-oasnt-01, , <https://datatracker.ietf.org/doc/html/draft-thallapelly-oasnt-01>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC4648]
Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, , <https://www.rfc-editor.org/rfc/rfc4648>.
[RFC6234]
Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, , <https://www.rfc-editor.org/rfc/rfc6234>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.

8.2. Informative References

[I-D.schrock-action-evidence-boundary]
Schrock, I., "The Action Evidence Boundary for Consequential Agent Effects", Work in Progress, Internet-Draft, draft-schrock-action-evidence-boundary-03, , <https://datatracker.ietf.org/doc/html/draft-schrock-action-evidence-boundary-03>.
[I-D.schrock-canonical-action-identifier]
Schrock, I., "The Canonical Action Identifier (CAID)", Work in Progress, Internet-Draft, draft-schrock-canonical-action-identifier-01, , <https://datatracker.ietf.org/doc/html/draft-schrock-canonical-action-identifier-01>.
[RFC3986]
Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/rfc/rfc3986>.

Appendix A. Test Vectors

The derivation vectors below are byte-reproducible: they are generated from the shipped canonicalization by docs/ietf/caid/gen-vectors-caid.mjs in the implementation repository, and unlike the signature vectors of the core document they involve no randomness. The named-human refusal vector involves an ECDSA signature and is verified rather than compared.

A.1. P1: CAID derivation

Action type payment.transfer, parameters amount=100.00, payee=acct_9.

canonical action  payment.transfer|amount=100.00&payee=acct_9
adg               YlHp3M4JIWFPPZIVAwAmYOBOMfUyb2bjE6ve3AD2iaQ
CAID              oasnt:caid:1:YlHp3M4JIWFPPZIVAwAmYOBOMfUyb2bjE6ve3AD2iaQ

This vector is deterministic: any conforming implementation reproduces these exact octets.

A.2. P2: CAID mismatch

The evidence above is presented for a different effect: amount=9000.00, payee=acct_EVIL.

executing canonical action  payment.transfer|amount=9000.00&payee=acct_EVIL
CAID-effect                 oasnt:caid:1:EWy_PVFw3FxdZIk6AEpEJ5HxhAsCJQnSq7P1jPHg6gc
CAID-evidence               oasnt:caid:1:YlHp3M4JIWFPPZIVAwAmYOBOMfUyb2bjE6ve3AD2iaQ

The octet strings differ; the outcome is a refusal (caid-mismatch).

A.3. P2b: CAID mismatch, escaping load-bearing

The single parameter (a, b&c=d) and the parameter set (a, b), (c, d) canonicalize identically if the escaping rules of the core document are ignored, and must not under them.

canonical, single parameter  payment.transfer|a=b\&c\=d
CAID                         oasnt:caid:1:4u_wRl1BAfeJRhqTs268VI1_kCw03xEah5PmylQOd1M
canonical, two parameters    payment.transfer|a=b&c=d
CAID                         oasnt:caid:1:YE3P-GAUpmAvZdKvqezf1RBMlLCdpt0e0deVj5vBrps

The octet strings differ, and differ only because the escaping is applied. Presenting evidence for either action against the other as the effect refuses (caid-mismatch) at the CAID layer, rather than surfacing an adg error.

A.4. P3: carried-form refusals

Each of the following values MUST be refused by the carried form of the derivation rather than prefixed:

""                                             (empty)
"short"                                        (wrong length)
42 or 44 characters of the base64url alphabet  (wrong length)
43 characters ending in "="                    (padding)
any character outside ALPHA / DIGIT / "-" / "_"

A.5. P4: named-human refusal (verified, not compared)

A token signed by the core document's published test key, with every claim valid except sub, which names mallory while enrollment records agent-1 for the key. Verification refuses with sub-mismatch and no other reason. The signature is not byte-reproducible; regenerate and verify with the tool named above.

Change Log

RFC Editor: please remove this section before publication.

Since -00:

Acknowledgments

The composition questions raised by Iman Schrock on the WIMSE mailing list, in particular whether the adg-to-CAID derivation should be fixed normatively or left to each executor adapter, prompted this profile. His executor-implementer review of the -00 text contributed the cross-profile observation now stated in Section 6.4, the shape of the escaping vector in Appendix A, and the single-use ordering defect corrected in Section 4.1, a case where the published text permitted an executor to consume an authorization while refusing the effect it authorized.

Author's Address

Arun Thallapelly
OmniArx