Skip to content

Schema and Instance Model

dweller long gone edited this page May 27, 2026 · 2 revisions

Schema and Instance Model

ASN.1 Instance Builder uses a compact Schema Model as the shared contract between the ASN.1 definition parser, diagnostics, DER builder, browser app, and host integrations.

Supported ASN.1 Kinds

The current core prototype supports these schema kinds:

  • BOOLEAN.
  • INTEGER, including negative values and named integer values such as v1(0).
  • BIT STRING.
  • OCTET STRING.
  • NULL.
  • OBJECT IDENTIFIER.
  • UTF8String.
  • PrintableString.
  • IA5String.
  • UTCTime.
  • GeneralizedTime.
  • ENUMERATED.
  • SEQUENCE.
  • SET.
  • CHOICE.
  • SEQUENCE OF.
  • SET OF.
  • References to defined types.
  • Low-form context-specific EXPLICIT and IMPLICIT tags, such as [0] EXPLICIT UTF8String.
  • Module tag defaults from EXPLICIT TAGS, IMPLICIT TAGS, and AUTOMATIC TAGS headers.
  • Automatic low-form context-specific tags for untagged SEQUENCE, SET, and CHOICE components.
  • DEFAULT fields for BOOLEAN, INTEGER, and ENUMERATED values.
  • Binary inputs as compact HEX, byte arrays, { hex }, { utf8 }, or { base64 }.
  • OBJECT IDENTIFIER inputs by dotted decimal value, built-in PKI names, or schema-provided oidNames.

Basic Module Shape

The definition parser accepts simple modules shaped like:

Example DEFINITIONS ::= BEGIN
Person ::= SEQUENCE {
  name UTF8String,
  age INTEGER OPTIONAL,
  email IA5String OPTIONAL
}
END

Tagging

Tagged fields can be written with explicit tagging mode:

TaggedPerson ::= SEQUENCE {
  name [0] EXPLICIT UTF8String,
  age [1] IMPLICIT INTEGER OPTIONAL
}

Module headers can define the default tagging mode:

ImplicitHeader DEFINITIONS IMPLICIT TAGS ::= BEGIN
VersionedSerial ::= SEQUENCE {
  version [0] Version DEFAULT v1,
  serialNumber INTEGER
}
END

When a module uses EXPLICIT TAGS or IMPLICIT TAGS, manually tagged types can omit EXPLICIT or IMPLICIT and the module default is applied.

When a module uses AUTOMATIC TAGS, untagged SEQUENCE, SET, and CHOICE components receive low-form context-specific implicit tags in field order while manually tagged components keep their existing tag numbers.

Only context-specific low-form tag numbers from 0 through 30 are supported.

Named Numbers and Defaults

Named enumerations and simple defaults are supported:

Status ::= ENUMERATED {
  ok(0),
  warning(1),
  failed(2)
}

DefaultRecord ::= SEQUENCE {
  enabled BOOLEAN DEFAULT TRUE,
  retryCount INTEGER DEFAULT 3,
  status Status DEFAULT ok
}

Default fields are omitted when the instance omits the field or provides the same value as the default.

Named integer values support X.509-style definitions:

Version ::= INTEGER {
  v1(0),
  v2(1),
  v3(2)
}

TBSCertificatePrefix ::= SEQUENCE {
  version [0] EXPLICIT Version DEFAULT v1,
  serialNumber INTEGER
}

Instance JSON

Instance JSON is the canonical data shape consumed by validateInstance() and createInstance().

The browser app's Form view is a schema-driven editor for this same value shape. It helps users create and update compatible instance JSON, but it does not introduce a separate DER-generation path.

Primitive values use plain JSON values when possible:

  • BOOLEAN: true or false.
  • INTEGER: number or named number string.
  • ENUMERATED: named value string or numeric value.
  • String-like types: JSON string.
  • Time types: ASN.1 time string, such as 260520000000Z.
  • OBJECT IDENTIFIER: dotted decimal string, built-in OID name, or schema-provided OID name.
  • NULL: null.

Constructed values use JSON objects or arrays:

  • SEQUENCE and SET: object keyed by field name.
  • SEQUENCE OF and SET OF: array.
  • CHOICE: { "selected": "alternativeName", "value": ... }.

Binary Inputs

OCTET STRING values and BIT STRING byte payloads can be provided in several forms:

{
  "payload": { "hex": "de ad be ef" },
  "label": { "utf8": "hello" },
  "flags": { "bytes": { "base64": "oA==" }, "unusedBits": 5 }
}

Accepted byte input forms are:

  • Uint8Array when using the API directly.
  • Number arrays, where each entry must be in 0..255.
  • Compact HEX strings.
  • { "hex": "..." }.
  • { "utf8": "..." }.
  • { "base64": "..." }.

BIT STRING uses { "bytes": ..., "unusedBits": ... }. Diagnostics reject invalid byte values and invalid empty BIT STRING unused-bit combinations.

OID Names

OID values can use dotted decimal text or known names:

{
  "algorithm": "sha256WithRSAEncryption"
}

Hosts can also attach an oidNames map to the Schema Model:

{
  "name": "Example",
  "tagDefault": "explicit",
  "oidNames": { "exampleAlgorithm": "1.2.3.4.5" },
  "types": []
}

Current Parser Limits

The parser is intentionally a subset parser.

The following are planned or out of scope for the current slice:

  • Constraints.
  • Extension markers.
  • Parameterized types.
  • Value assignments.
  • Macros.
  • Full module imports.
  • High-form tag numbers.

Use schema and instance diagnostics before building DER from untrusted or user-edited definitions.

Clone this wiki locally