01 Asn1EN
AIC ASN.1 Type Definitions
Corresponds to specification version v1.7.1. Known limitations (parameter-level subset validation) are listed in
02-code-map.md. Key files:gateway-core/aic.go,gateway-core/decision.go,gateway-core/constraints.go
AIC Overall Structure
AIC ::= SEQUENCE {
version INTEGER DEFAULT 1,
agentId UTF8String (SIZE(1..256)),
principalUid PrincipalUid,
capabilities SEQUENCE SIZE(0..256) OF Capability,
delegationMode DelegationMode DEFAULT authorized,
authorizationConstraints [0] EXPLICIT SEQUENCE SIZE(0..32) OF Capability OPTIONAL,
delegationAuthorization DelegationAuthorization,
extensions [1] EXPLICIT Extensions OPTIONAL
}
DelegationMode ::= INTEGER {
authorized (0),
representative (1)
} (0..1)
| Field | Type | Constraint | Description |
|---|---|---|---|
version |
INTEGER DEFAULT 1 | Only defines v1 | AIC version number |
agentId |
UTF8String | SIZE(1..256) | Agent unique identifier, unchanged across renewals |
principalUid |
SEQUENCE | See below | Principal identity identifier |
capabilities |
SEQUENCE OF Capability | 0–256 entries | CA-certified Capability declarations |
delegationMode |
INTEGER (0..1) | authorized / representative | Delegation mode |
authorizationConstraints |
SEQUENCE OF Capability OPTIONAL | 0–32 entries | Authorization boundary constraints (added in v1.6) |
delegationAuthorization |
SEQUENCE | See below | Principal signature evidence |
extensions |
Extensions OPTIONAL | ≤32 entries | General extension slot |
delegationAuthorizationis a required field. In dual-certificate deployment, both the handshake certificate and authorization certificate are complete AICs and MUST carry DA (see08-dual-cert.md).
authorizationConstraints
Reuses the Capability container; schemeId MUST be "varwof/constraint-v1" (recommended by specification); for backward compatibility, the code also accepts "constraint" and "constraint-v1"; other schemeIds are skipped, and capabilityId identifies the specific constraint type:
| capabilityId | parameters format | Description |
|---|---|---|
network:cidr |
["10.0.0.0/8", "192.168.0.0/16"] |
Allowed IP ranges |
session:max-concurrent |
{"max": 5} |
Maximum concurrent Agent instances |
time:window |
{"start": "22:00", "end": "06:00"} |
Allowed execution time window |
Maximum constraint count ≤ 32 entries (unified at wire format + CA issuance phase), single parameters ≤ 512 bytes.
Design principle ("constrained but not overstepping"):
- Only authorization boundary constraints, not runtime policies (timeout/retry/rate-limiting/routing)
- Determined by the authorizer, varies per individual, infrequent changes
- Verified offline by the gateway during the TLS handshake phase, no external system dependency
Encoding Tag Conventions (Context Tags)
For cross-platform, cross-language stable implementation, encoding tags follow these rules (v1.7.1):
- Required fields use universal tags (INTEGER / UTF8String / OCTET STRING / SEQUENCE, etc.) without context tags; required fields with the same tag are decoded in structural order without ambiguity.
- All OPTIONAL fields uniformly use context-specific explicit tags
[n] EXPLICIT, numbered starting from 0 in field appearance order within the structure; numbers are unique within the same structure but can repeat across structures. - Standard external types (
AlgorithmIdentifier,Extensions, etc.) follow RFC 5280 encoding conventions and are not subject to this rule (e.g.,AlgorithmIdentifier.parametersremains tagless OPTIONAL). - DEFAULT field encoding: DER allows omitting fields equal to their default value; implementations MUST tolerate both forms; Go
encoding/asn1currently always encodes DEFAULT fields (not minimal DER, but parseable).
| Structure | Field | tag | Description |
|---|---|---|---|
AIC |
authorizationConstraints | [0] |
Same SEQUENCE tag as capabilities / delegationAuthorization, must be distinguished |
AIC |
extensions | [1] |
At end of structure, explicit tag prevents future ambiguity |
DelegationAuthTBS |
authorizationConstraints | [0] |
Same SEQUENCE tag as capabilities, must be distinguished |
PrincipalAuthorization |
authorizationConstraints | [0] |
Same SEQUENCE tag as grants, must be distinguished |
PrincipalAuthorization |
delegationPolicy | [1] |
Same SEQUENCE tag as grants / constraints, must be distinguished |
PrincipalAuthorization |
extensions | [2] |
All SEQUENCE field tags within structure are unique |
DelegationPolicy |
maxSessionHours | [0] |
Distinguished from three required INTEGER fields |
PrincipalUid |
hashAlgo | [0] |
Optional at end |
Capability |
parameters | [0] |
Existing convention, unchanged |
Note:
DelegationMode/DelegationModeEnumis defined asINTEGER+ named constants + range constraint ((0..1)), natively supported by Goencoding/asn1, ensuring cross-language implementation consistency.
PrincipalUid
PrincipalUid ::= SEQUENCE {
version INTEGER (0..255) DEFAULT 1,
realm UTF8String (SIZE(1..128)),
identifier UTF8String (SIZE(1..256)),
keyHash OCTET STRING (SIZE(1..64)),
hashAlgo [0] EXPLICIT AlgorithmIdentifier OPTIONAL
}
-- When hashAlgo is omitted, defaults to SHA-256 (OID 2.16.840.1.101.3.4.2.1); keyHash = hashAlgo(SPKI);
-- The specification only supports hash algorithms with output length ≤64 bytes
-- (SHA-2/SHA-3 family, BLAKE2/BLAKE3, Chinese SM3, etc. all satisfy this)
| Field | Description |
|---|---|
realm |
Global namespace (e.g., organization domain corp.com), SIZE(1..128) |
identifier |
Unique identifier within the namespace (e.g., zhangsan), SIZE(1..256) |
keyHash |
Hash of SPKI computed per hashAlgo (SHA-256/SM3 = 32 bytes), length determined by algorithm |
hashAlgo |
Hash algorithm identifier for keyHash computation; defaults to SHA-256 when omitted |
keyHash binds to SPKI rather than certificate fingerprints or pure identity strings. Rationale: certificate fingerprints change on certificate renewal, breaking identity continuity; pure identity strings have no cryptographic binding and cannot verify ownership offline; SPKI hashes enable offline ownership verification, maintain identity continuity across certificate renewals with the same key, and invalidate all associated authorization on key replacement. When a new certificate is issued with the same key pair, SPKI remains unchanged and the Agent certificate automatically continues.
keyHash computation MUST use the hash algorithm declared in
hashAlgoon the subject SPKI (keyHash = hashAlgo(SPKI)); when omitted, defaults to SHA-256 (OID 2.16.840.1.101.3.4.2.1). The specification only supports hash algorithms with output length ≤ 64 bytes (constrained bykeyHash OCTET STRING (SIZE(1..64))): current implementation (pki-types P1-A-12) already supports full SHA-2/SHA-3 family computation — SHA-256 (32 bytes) / SHA-384 (48) / SHA-512 (64) / SHA3-256 (32) / SHA3-384 (48) / SHA3-512 (64), keyHash length varies with algorithm output length without structure modification; BLAKE2/BLAKE3, Chinese SM3, etc. with output length ≤64 bytes register OID+length mapping only under pki-types zero-external-dependency policy (explicit "unsupported" without silent degradation), implementers can provide their own computation on the dependency side; if future support for algorithms with output length exceeding 64 bytes (e.g., SHAKE long output) is needed, AIC version must be upgraded and SIZE constraint relaxed.
Security policy: Principal key rotation will cause
PrincipalUid.String()to change (due to KeyHash change). In this case, already-issued existing Agent certificates MUST be invalidated through the revocation process (CRL/OCSP). This design enforces strong binding between the principal key and Agent authorization, preventing identity spoofing and conforming to the short-lived certificate security model.The communication format
realm:identifier:keyFingerprintis for human reading and log output only; machine comparison MUST be based on ASN.1 structure deserialization. For subject lookup/association (cascading revocation, audit, certificate queries), this can be done via database index orPrincipalUid.realm/identifierfields; this lookup is for management association only, authorization binding and revocation still use keyHash as the authoritative source.
Capability
Capability is the only generic container in the protocol, with semantics defined by schemeId.
Capability ::= SEQUENCE {
schemeId UTF8String (SIZE(1..128)),
capabilityId UTF8String (SIZE(1..256)),
parameters [0] EXPLICIT OCTET STRING (SIZE(0..4096)) OPTIONAL
}
Glob matching rules:
| Pattern | Meaning | Example |
|---|---|---|
http:GET:/api/v1/users |
Exact match | Only this path |
http:GET:/api/v1/* |
Single-segment wildcard (* does not include /) |
/api/v1/users |
http:*:/api/v1/* |
Wildcard HTTP method | Any method on /api/v1/ |
varwof-gateway-v1:* |
All capabilities under scheme | Any capabilityId under this schemeId |
/api/v1/** |
Cross-path arbitrary depth | /api/v1/users, /api/v1/users/roles |
Reason
Delegation authorization reason description, for audit and display purposes, does not participate in permission decisions. Semantics are determined by the authorizer. reason is only used in DelegationAuthorization / DelegationAuthTBS (describing the reason for this delegation), not included in PrincipalAuthorization.
Reason ::= SEQUENCE {
reasonCode UTF8String (SIZE(1..64)), -- Machine-identifiable standard reason code (controlled vocabulary, e.g., "SCHEDULED_MAINTENANCE"), should be as short as possible
description UTF8String (SIZE(1..512)) -- Human-readable detailed description (e.g., "Due to v2.3.1 launch, old cache needs temporary shutdown")
}
| Field | Type | Constraint | Description |
|---|---|---|---|
reasonCode |
UTF8String | SIZE(1..64), MUST be non-empty | Machine-identifiable standard reason code (controlled vocabulary, e.g., SCHEDULED_MAINTENANCE), should be as short as possible |
description |
UTF8String | SIZE(1..512), MUST be non-empty | Human-readable detailed description (e.g., Due to v2.3.1 launch, old cache needs temporary shutdown) |
Added in v1.7.1. Both
reasonCodeanddescriptionMUST be present;Reasonis a required field inDelegationAuthorization/DelegationAuthTBS(authorization must always have a reason).reasonCodeuses a controlled vocabulary: values use SCREAMING_SNAKE style (e.g.,SCHEDULED_MAINTENANCE,AUTO_RENEWAL), should be as short as possible (numbers or brief text, ≤64); new values require registration (currently a maintained whitelist by implementers, registration mechanism TBD).
DelegationAuthorization
DelegationAuthorization ::= SEQUENCE {
reason Reason, -- v1.7.1 addition: delegation authorization reason (required)
requestedLifetime INTEGER (1..86400), -- SHOULD 3600–86400; API input layer 0 → 3600 normalization, wire value is always 1..86400
timestamp GeneralizedTime,
nonce OCTET STRING (SIZE(32)),
signatureAlgorithm AlgorithmIdentifier,
signatureValue OCTET STRING
}
Design decision: signatureAlgorithm / signatureValue are flat, not merged into a nested Signature type (v1.7.1 finalized, reviewed and confirmed 2026-08-06)
In DelegationAuthorization, the signature algorithm and signature value are flat as two parallel fields:
signatureAlgorithm AlgorithmIdentifier+signatureValue OCTET STRING, consistent with the RFC 5280 §4.1Certificate ::= SEQUENCE { tbsCertificate, signatureAlgorithm, signatureValue }top-level three-segment convention (CMS/PKCS#7 is the same). Rationale:
- Unified parsing path: Verifiers use the same parsing order (first get algorithm OID, then get signature value) for both CA signatures and principal signatures; no need for two sets of parsing logic for dual-layer signatures;
- Convention consistency: X.509/CMS both use flat structure; merging into nested
Signature ::= SEQUENCE { algorithm, value }is non-conventional with no security or functional benefit;- No reuse need: The signature structure currently only appears in DA; if reuse is needed in the future, a separate type can be defined in a new version without affecting the existing wire format.
signatureAlgorithm / signatureValue MUST NOT be merged into a nested SEQUENCE.
nonce: Required 32 bytes, for anti-replayrequestedLifetime: 1–86400 seconds (SHOULD 3600–86400), default 3600 (1 hour). Wire value is always 1..86400; "0 → 3600" only exists at API input layer normalization (when caller passes 0, treated as default 3600); the value encoded into TBS/DA must already be within the 1..86400 range.timestamp: MUST be UTC (GeneralizedTime Z form)reason: Added in v1.7.1, required, positioned at the start of the structure; same delegation reason asDelegationAuthTBS.reason(covered by signature within TBS)
DelegationAuthTBS (Signature-Covered Structure)
The principal's private key signs the DER encoding of the following structure:
DelegationAuthTBS ::= SEQUENCE {
version INTEGER DEFAULT 1,
agentId UTF8String (SIZE(1..256)),
principalUid PrincipalUid,
reason Reason, -- v1.7.1 addition: delegation authorization reason (required, covered by signature)
capabilities SEQUENCE SIZE(0..256) OF Capability,
delegationMode DelegationMode,
authorizationConstraints [0] EXPLICIT SEQUENCE SIZE(0..32) OF Capability OPTIONAL,
requestedLifetime INTEGER (1..86400), -- SHOULD 3600–86400
timestamp GeneralizedTime, -- MUST use UTC (Z form)
nonce OCTET STRING (SIZE(32))
}
v1.6 added the authorizationConstraints field. For backward compatibility, this field is OPTIONAL. Old certificates without this field are not affected during verification.
Design decision: DelegationAuthTBS does not contain Agent public key hash (agentKeyHash) (v1.7.1 finalized, reviewed and confirmed 2026-08-06)
1. Responsibility model: Current AI/Agents belong to the machine domain and do not possess legal entity status; the authorization responsibility principal is the natural person (anchored by principalUid.keyHash). The user/responsible principal only needs to sign over the "authorization scope" (agentId + capabilities + authorization boundary + authorization reason + lifetime + nonce); the Agent's "identity ↔ public key" binding is completed by the CA at certificate issuance time (CSR key proof + certificate-level SPKI binding), no need to redundantly enter the authorization evidence chain.
2. Simplicity: The AIC certificate's TBSCertificate already contains the Agent SPKI; adding agentKeyHash to TBS is redundant information that increases wire format complexity and user review burden (requiring a natural person to verify key fingerprints is impractical).
3. Trust boundary: The remaining risk (key-swap in the issuance channel: replacing the CSR public key between user confirmation and CA issuance) belongs to the "uncontrolled issuance channel" scenario, on the same trust root/channel breach boundary as CA private key leakage; this specification assumes the issuance channel is controlled.
4. Evolution reserve: When AI/Agents obtain legal entity status (becoming independent rights/obligation subjects), or when deployment requires a completely untrusted issuance channel,
agentKeyHash(hashAlgo(Agent SPKI)) can be added through TBS version upgrade in a backward-compatible manner, making the principal's signature cover "this public key authorized to this agentId," thereby including the Agent itself in the authorization evidence chain. Old certificates and old verification logic are unaffected (distinguished by the version field, following the v1.6 → v1.7 evolution pattern).
v1.7.1:
reasonis located inDelegationAuthTBS(after principalUid) andDelegationAuthorization(at the start of the structure), both are required — authorization must always have a reason; thereasonwithin TBS is covered by the principal signature, meaning the principal is aware of the delegation reason when signing.
PrincipalAuthorization
PrincipalAuthorization ::= SEQUENCE {
version INTEGER DEFAULT 1,
grants SEQUENCE SIZE(0..256) OF Capability,
authorizationConstraints [0] EXPLICIT SEQUENCE SIZE(0..32) OF Capability OPTIONAL,
delegationPolicy [1] EXPLICIT DelegationPolicy OPTIONAL,
extensions [2] EXPLICIT Extensions OPTIONAL
}
DelegationPolicy ::= SEQUENCE {
version INTEGER DEFAULT 1,
maxAgents INTEGER DEFAULT 1,
allowedMode DelegationModeEnum DEFAULT authorizedOnly,
maxSessionHours [0] EXPLICIT INTEGER OPTIONAL
}
DelegationModeEnum ::= INTEGER {
authorizedOnly (0),
representativeAllowed (1)
} (0..1)
| Field | Type | Constraint | Description |
|---|---|---|---|
version |
INTEGER DEFAULT 1 | Only defines v1 | Version number |
grants |
SEQUENCE OF Capability | ≤ 256 entries | Principal's allowed capability grant set. When used directly = permission ceiling; when delegating = upper bound for Agent capabilities |
authorizationConstraints |
SEQUENCE OF Capability OPTIONAL | SIZE(0..32) | v1.6.1. Principal-level authorization boundary constraints, defining under what conditions the Principal exercises authorization. Reuses Capability container, schemeId MUST be "varwof/constraint-v1" (recommended by specification, backward compatible with "constraint" / "constraint-v1"). CA issuance phase and wire format unified limit of 32 entries |
delegationPolicy |
SEQUENCE | OPTIONAL | Delegation policy |
extensions |
Extensions OPTIONAL | ≤ 32 entries | General extension slot |
Delegation constraints (v1.6):
- Currently only supports Principal → Agent single-level delegation (chainDepth = 0)
- Multi-level delegation chain (FUTURE): Authorized Agents can use their own private keys to sign new DelegationAuthorization for lower-level Agents, forming a recursively verifiable cryptographic evidence chain
- Agent certificates MUST be end-entity certificates (cA = FALSE)
- Current Agents MUST NOT derive lower-level Agents
DelegationDepthControl (FUTURE — specification reserve, not yet implemented)
Placed in AIC extensions slot, OID 1.3.6.1.4.1.66257.1.1.4:
DelegationDepthControl ::= SEQUENCE {
chainDepth INTEGER (0..255), -- OID .1.1.4.1
maxDepth INTEGER (0..255) -- OID .1.1.4.2
}
| Field | Type | Description |
|---|---|---|
chainDepth |
INTEGER (0..255) | Current delegation level. Direct authorization = 0, first-level delegation = 1, and so on |
maxDepth |
INTEGER (0..255) | Maximum allowed delegation depth. Gateway verifies chainDepth ≤ maxDepth, exceeding = rejection |
Design principles:
- This extension is only used when multi-level delegation chains are enabled; single-level deployment can omit it
- Each delegation level's
DelegationAuthorizationis independently signed; tampering with any hop causes the entire chain to fail - Verifiers complete offline: parse certificate extension → verify signature level by level → check
chainDepth ≤ maxDepth, no external service dependency - In multi-level delegation mode, when an Agent with
chainDepth = Ndelegates to a lower level, the DelegationDepthControl it constructs haschainDepth = N+1withmaxDepthunchanged - Not yet implemented: Current gateway only supports single-level delegation (direct authorization = 0); multi-level delegation chain CA issuance logic, gateway verification pipeline, and audit tracing are all FUTURE
Permission Intersection Formula
CapabilityId-level intersection:
EffectiveCapability = P_grants ∩ C_agent ∩ T_policy
| Set | Source | Description |
|---|---|---|
P_grants |
PrincipalAuthorization.grants | Capabilities the principal allows to grant |
C_agent |
AIC.capabilities | CA-certified Agent capability declarations |
T_policy |
Gateway local policy | Deployment-side configured policy constraints |
Capability Parameters Intersection Semantics (clarified in v1.6):
For each matching Capability:
if C_agent.parameters exceeds the boundary range of P_grants.parameters:
this Capability is considered invalid (filtered or rejected)
else:
C_agent.parameters are adopted entirely (taking the Agent's values, but not exceeding boundaries)
Example:
| Principal Authorization | Agent Declaration | Result |
|---|---|---|
mysql:SELECT:* (max_rows=1000) |
mysql:SELECT:* (max_rows=100) |
✅ Pass, take max_rows=100 |
mysql:SELECT:* (max_rows=1000) |
mysql:SELECT:* (max_rows=5000) |
❌ Reject (exceeds principal boundary) |
http:GET:/api/v1/* |
http:GET:/api/v1/users |
✅ Pass, take Agent's specific path |
The principal defines the maximum permission boundary; the Agent declares specific operation parameters. Agent parameters MUST be within the principal authorization range; exceeding = rejection.
Execution layer (clarified in v1.7.1): This parameter-level subset validation is mechanically executed by the CA at the issuance phase (at the same level as capability-level subset:
capabilities ⊆ grantswith each parameter not exceeding bounds); at gateway runtime, capability-levelP∩C∩Tintersection is executed without per-parameter comparison (parameter boundaries are already consolidated at issuance). This rule only applies to the capability layer (capabilities/grants); the authorization constraint layer (authorizationConstraints) does not apply subset relationships — PA and AIC constraints are independently checked at their respective layers (v1.6.1 preserved).
Certificate Size Constraints
| Certificate Type | Recommended Limit | Hard Limit | Description |
|---|---|---|---|
| All-protocol safety limit | 12KB | 16KB | DER encoding ensures TCP/HTTP/DTLS/QUIC all four gateways compatible. 16KB corresponds to QUIC CRYPTO_BUFFER_EXCEEDED (quic-go hard limit); exceeding = handshake failure |
| Handshake certificate (AIC lightweight) | 8KB | 16KB | Used for mTLS/DTLS/QUIC handshake. In dual-certificate deployment, contains agentId + principalUid + delegationMode + DelegationAuthorization; capabilities at least one entry (specific placeholder capabilities defined by deployment per registry) |
| Full authorization certificate (all constraints + extensions) | 64KB | 128KB | Transmitted via application layer after handshake completion. Exceeding 128KB MUST be rejected by the gateway |
| Capabilities entries | ≤ 256 entries | — | Approximately 250 capability declarations ≈ 12KB DER. 256 is the ASN.1 SEQUENCE SIZE upper limit |
v1.6: See
08-dual-cert.mdfor dual-certificate deployment details. The handshake certificate only containsagentId+principalUid+delegationMode+DelegationAuthorization(capabilities at least one entry, specific placeholder capabilities defined by deployment per registry), always under 8KB, ensuring stable pass-through across all transport layer protocols.