@blamejs/pki 0.6.13 → 0.6.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +1 -1
  3. package/index.js +1 -1
  4. package/lib/acme.js +59 -815
  5. package/lib/asn1-der.js +7 -245
  6. package/lib/attrcert-sign.js +12 -260
  7. package/lib/attrcert-verify.js +1 -7
  8. package/lib/byte-reader.js +0 -8
  9. package/lib/byte-writer.js +0 -11
  10. package/lib/cbor-det.js +0 -54
  11. package/lib/cmc-build.js +15 -357
  12. package/lib/cmc-verify.js +6 -239
  13. package/lib/cmp-build.js +41 -317
  14. package/lib/cmp-session.js +73 -760
  15. package/lib/cmp-verify.js +32 -488
  16. package/lib/cms-compress.js +3 -32
  17. package/lib/cms-decrypt.js +29 -294
  18. package/lib/cms-encrypt.js +14 -234
  19. package/lib/cms-sign.js +29 -324
  20. package/lib/cms-verify.js +9 -500
  21. package/lib/composite-kem.js +2 -102
  22. package/lib/composite-sig.js +1 -77
  23. package/lib/constants.js +0 -249
  24. package/lib/crl-sign.js +9 -237
  25. package/lib/crl-verify.js +1 -10
  26. package/lib/crmf-sign.js +19 -198
  27. package/lib/crmf-verify.js +1 -12
  28. package/lib/csr-sign.js +3 -34
  29. package/lib/csr-verify.js +1 -12
  30. package/lib/ct.js +28 -253
  31. package/lib/edwards-point.js +10 -44
  32. package/lib/est.js +28 -764
  33. package/lib/framework-error.js +4 -182
  34. package/lib/guard-all.js +1 -58
  35. package/lib/guard-async.js +1 -36
  36. package/lib/guard-bytes.js +6 -650
  37. package/lib/guard-compress.js +5 -102
  38. package/lib/guard-crypto.js +1 -40
  39. package/lib/guard-der.js +2 -93
  40. package/lib/guard-encoding.js +2 -60
  41. package/lib/guard-header.js +1 -36
  42. package/lib/guard-identifier.js +7 -531
  43. package/lib/guard-intrinsic.js +1 -150
  44. package/lib/guard-json.js +10 -73
  45. package/lib/guard-limits.js +1 -77
  46. package/lib/guard-list.js +1 -49
  47. package/lib/guard-name.js +3 -209
  48. package/lib/guard-parsed.js +7 -335
  49. package/lib/guard-range.js +1 -71
  50. package/lib/guard-secret.js +1 -102
  51. package/lib/guard-text.js +1 -64
  52. package/lib/guard-time.js +1 -97
  53. package/lib/hpke.js +3 -105
  54. package/lib/http-digest.js +14 -142
  55. package/lib/http-retry-after.js +1 -47
  56. package/lib/http-transport.js +21 -131
  57. package/lib/inspect.js +30 -284
  58. package/lib/ip-utils.js +6 -47
  59. package/lib/jose.js +7 -142
  60. package/lib/key.js +2 -67
  61. package/lib/lint.js +9 -194
  62. package/lib/merkle.js +1 -27
  63. package/lib/mime.js +9 -82
  64. package/lib/ocsp-request-verify.js +1 -14
  65. package/lib/ocsp-verify.js +1 -82
  66. package/lib/ocsp.js +11 -169
  67. package/lib/oid.js +5 -337
  68. package/lib/path-validate.js +103 -1492
  69. package/lib/pbes2.js +2 -89
  70. package/lib/pkcs12-build.js +31 -379
  71. package/lib/pki-build.js +64 -290
  72. package/lib/rc2.js +2 -18
  73. package/lib/rfc3339.js +4 -27
  74. package/lib/scep.js +59 -233
  75. package/lib/schema-all.js +0 -122
  76. package/lib/schema-attrcert.js +4 -146
  77. package/lib/schema-c509.js +153 -802
  78. package/lib/schema-cmc.js +5 -220
  79. package/lib/schema-cmp.js +2 -223
  80. package/lib/schema-cms.js +13 -427
  81. package/lib/schema-crl.js +5 -68
  82. package/lib/schema-crmf.js +6 -167
  83. package/lib/schema-csr.js +1 -54
  84. package/lib/schema-csrattrs.js +2 -87
  85. package/lib/schema-engine.js +0 -152
  86. package/lib/schema-ocsp.js +0 -117
  87. package/lib/schema-pkcs12.js +2 -93
  88. package/lib/schema-pkcs8.js +3 -35
  89. package/lib/schema-pkix.js +24 -655
  90. package/lib/schema-smime.js +0 -54
  91. package/lib/schema-tsp.js +3 -99
  92. package/lib/schema-x509.js +4 -63
  93. package/lib/shbs.js +11 -95
  94. package/lib/sign-scheme.js +2 -97
  95. package/lib/sigstore.js +9 -169
  96. package/lib/sleep.js +2 -8
  97. package/lib/smime.js +15 -408
  98. package/lib/tls-cert-compress.js +0 -62
  99. package/lib/trust.js +19 -185
  100. package/lib/tsp-sign.js +16 -270
  101. package/lib/validator-all.js +1 -30
  102. package/lib/validator-attcert.js +2 -46
  103. package/lib/validator-cose.js +2 -153
  104. package/lib/validator-keydesc.js +1 -37
  105. package/lib/validator-sig.js +1 -46
  106. package/lib/validator-tls.js +1 -88
  107. package/lib/validator-tpm.js +19 -122
  108. package/lib/verify-seam.js +1 -24
  109. package/lib/webauthn-mds.js +3 -400
  110. package/lib/webauthn.js +12 -833
  111. package/lib/webcrypto.js +5 -485
  112. package/lib/x509-sign.js +4 -108
  113. package/package.json +1 -1
  114. package/sbom.cdx.json +6 -6
@@ -30,22 +30,11 @@ var asn1 = require("./asn1-der.js");
30
30
 
31
31
  var TAGS = asn1.TAGS;
32
32
 
33
- // ---- context ---------------------------------------------------------
34
- // A walk receives ctx = { E, prefix, oid } where E(code, message) constructs
35
- // (does not throw) the format's typed error, prefix names the error family
36
- // ("x509", "crl", ...) and oid is the OID registry (for name resolution in a
37
- // build fn). _fail throws so a schema node reads as a single expression.
38
33
 
39
34
  function _fail(ctx, code, message) {
40
35
  throw ctx.E(code, message);
41
36
  }
42
37
 
43
- // ---- shape assertions ------------------------------------------------
44
- // A schema's `assert` mode is a real behavior-preservation control: some
45
- // hand-written guards checked the universal SEQUENCE tag (algorithmIdentifier,
46
- // Name), others checked only that the node had children (Validity, SPKI, the
47
- // tbs body, an AttributeTypeAndValue). Collapsing them to one "is a SEQUENCE"
48
- // check would silently change behavior on SET-wrapped input, so each is kept.
49
38
 
50
39
  function _assertShape(schema, node, ctx) {
51
40
  var mode = schema.assert || "sequence";
@@ -58,16 +47,10 @@ function _assertShape(schema, node, ctx) {
58
47
  _fail(ctx, schema.code, (schema.what || "value") + " must be a SET");
59
48
  }
60
49
  } else if (mode === "constructed") {
61
- // Bare constructed: the historical guards only required decoded children,
62
- // never a specific universal tag.
63
50
  if (!node.children) {
64
51
  _fail(ctx, schema.code, (schema.what || "value") + " must be a constructed value");
65
52
  }
66
53
  } else if (mode === "implicit") {
67
- // IMPLICIT [tag] SET/SEQUENCE OF or a fixed-field IMPLICIT [tag] SEQUENCE body:
68
- // the context tag replaces the universal tag, so the node is a context-class
69
- // constructed [tag] and its direct children are the items / positional fields
70
- // (no inner universal tag, no EXPLICIT unwrap).
71
54
  if (node.tagClass !== "context" || node.tagNumber !== schema.implicitTag || !node.children) {
72
55
  _fail(ctx, schema.code, (schema.what || "value") + " must be an IMPLICIT [" + schema.implicitTag + "] constructed value");
73
56
  }
@@ -91,49 +74,21 @@ function _assertArity(schema, kids, ctx) {
91
74
  }
92
75
  }
93
76
 
94
- // ---- leaf / value combinators ---------------------------------------
95
- // Leaves read a primitive off a node via the L1 codec; the codec's own
96
- // asn1/* errors propagate unchanged (the frozen oracle expects those codes on
97
- // the OID / INTEGER / string reads). `decode(fn)` hands the whole node to fn,
98
- // which owns its try/catch and code mapping. `any()` yields the node itself.
99
77
 
100
- // Leaves carry both directions: `read(node) -> value` and `write(value) -> DER TLV`,
101
- // so a single leaf definition drives decode (walk) and encode (build). A [tag]
102
- // IMPLICIT leaf's write emits the context-tagged TLV directly, mirroring its read.
103
78
  function _implicitIntContent(v) { return asn1.decode(asn1.build.integer(v)).content; }
104
79
  function oidLeaf() { return { kind: "leaf", read: asn1.read.oid, write: function (v) { return asn1.build.oid(v); } }; }
105
80
  function integerLeaf() { return { kind: "leaf", read: asn1.read.integer, write: function (v) { return asn1.build.integer(v); } }; }
106
81
  function boolean() { return { kind: "leaf", read: asn1.read.boolean, write: function (v) { return asn1.build.boolean(v); } }; }
107
82
  function octetString() { return { kind: "leaf", read: asn1.read.octetString, write: function (v) { return asn1.build.octetString(v); } }; }
108
83
  function bitString() { return { kind: "leaf", read: function (n) { var b = asn1.read.bitString(n); return { unusedBits: b.unusedBits, bytes: b.bytes }; }, write: function (v) { return asn1.build.bitString(v.bytes, v.unusedBits); } }; }
109
- // A [tag] IMPLICIT BIT STRING leaf (context-class primitive), the primitive-leaf
110
- // counterpart to implicitSetOf, for e.g. the PKCS#8 publicKey [1] (RFC 5958 sec. 2).
111
84
  function implicitBitString(tag) { return { kind: "leaf", read: function (n) { var b = asn1.read.bitStringImplicit(n, tag); return { unusedBits: b.unusedBits, bytes: b.bytes }; }, write: function (v) { return asn1.build.contextPrimitive(tag, Buffer.concat([Buffer.from([v.unusedBits]), v.bytes])); } }; }
112
- // A [tag] IMPLICIT OCTET STRING leaf (context-class primitive), the sibling of
113
- // implicitBitString, for e.g. the CMS SignerIdentifier subjectKeyIdentifier [0]
114
- // (RFC 5652 sec. 5.3). Yields the raw content bytes.
115
85
  function implicitOctetString(tag) { return { kind: "leaf", read: function (n) { return asn1.read.octetStringImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, v); } }; }
116
- // A [tag] IMPLICIT NULL leaf (context-class primitive, empty content), the sibling
117
- // of implicitBitString/implicitOctetString, for e.g. the OCSP CertStatus good [0] /
118
- // unknown [2] arms (RFC 6960 sec. 4.2.1). Yields null; rejects a constructed or
119
- // non-empty [tag] node fail-closed.
120
86
  function implicitNull(tag) { return { kind: "leaf", read: function (n) { return asn1.read.nullImplicit(n, tag); }, write: function () { return asn1.build.contextPrimitive(tag, Buffer.alloc(0)); } }; }
121
- // A [tag] IMPLICIT INTEGER leaf (context-class primitive), the integer sibling of
122
- // implicitBitString, for the RFC 3161 Accuracy millis [0] / micros [1] fields
123
- // (context-tagged primitive INTEGERs). Yields a BigInt; a constructed or wrong-tag
124
- // node fails asn1/* at the codec.
125
87
  function implicitInteger(tag) { return { kind: "leaf", read: function (n) { return asn1.read.integerImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, _implicitIntContent(v)); } }; }
126
- // implicitBoolean, for the RFC 5280 sec. 5.2.5 IssuingDistributionPoint scope flags
127
- // (context-tagged primitive BOOLEANs). DER value rules enforced (0x00/0xFF only).
128
88
  function implicitBoolean(tag) { return { kind: "leaf", read: function (n) { return asn1.read.booleanImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, Buffer.from([v ? 0xff : 0x00])); } }; }
129
89
  function any() { return { kind: "any" }; }
130
- // decode(fn, write?): a custom decode leaf; `write` is its optional paired encoder
131
- // (value -> DER TLV) so the same leaf drives both directions.
132
90
  function decode(fn, write) { return { kind: "decode", fn: fn, write: write }; }
133
91
 
134
- // time(ns): a UTCTime / GeneralizedTime value, asserting the tag before the
135
- // codec reads it (mirrors _parseValidityTime's x509/bad-time guard). Encodes as
136
- // UTCTime for years 1950..2049 and GeneralizedTime otherwise (RFC 5280 sec. 4.1.2.5).
137
92
  function time(ns) {
138
93
  return decode(function (n, ctx) {
139
94
  if (n.tagClass !== "universal" || (n.tagNumber !== TAGS.UTC_TIME && n.tagNumber !== TAGS.GENERALIZED_TIME)) {
@@ -146,24 +101,10 @@ function time(ns) {
146
101
  });
147
102
  }
148
103
 
149
- // ---- field descriptors (members of a seq) ---------------------------
150
104
 
151
105
  function field(name, schema) { return { fkind: "required", name: name, schema: schema }; }
152
106
  function optional(name, schema, opts) {
153
107
  opts = opts || {};
154
- // How the optional field is recognized at its position:
155
- // - default: a context [tag] (the certificate version [0] shape).
156
- // - tags: a context tag in the set, for an OPTIONAL field whose type is
157
- // itself a CHOICE of several context alternatives, e.g. the CRMF CertReqMsg
158
- // popo ProofOfPossession ([0]..[3]) sitting before the universal-SEQUENCE
159
- // regInfo (RFC 4211 sec. 3), where ANY of the CHOICE's tags marks it present.
160
- // - whenUniversal: the next element iff its universal tag is in the set, for
161
- // the CRL TBSCertList shape (bare INTEGER version, Time nextUpdate,
162
- // SEQUENCE revokedCertificates), disambiguated by tag and not a context [n].
163
- // - whenAny: the next element whatever its tag, for an OPTIONAL ANY like
164
- // AlgorithmIdentifier.parameters.
165
- // The recognizer lets _walkSeq CONSUME the element so a closed sequence can
166
- // reject whatever is left over (without it, a trailing ANY looks unconsumed).
167
108
  var match = opts.whenAny
168
109
  ? function () { return true; }
169
110
  : opts.whenUniversal
@@ -171,25 +112,16 @@ function optional(name, schema, opts) {
171
112
  : opts.tags
172
113
  ? function (n) { return isContextOneOf(n, opts.tags); }
173
114
  : function (n) { return isContext(n, opts.tag); };
174
- // default/defaultCode: `default` binds the DEFAULT value when the field is
175
- // absent. `defaultCode` opts the field into the X.690 sec. 11.5 walk-side reject
176
- // (DER: a component equal to its DEFAULT shall not be included), so a present
177
- // value equal to `default` (strict equality; Buffers by bytes) fails with
178
- // that code, so each format keeps its own reject-code family.
179
115
  return { fkind: "optional", name: name, schema: schema, tag: opts.tag, match: match,
180
116
  explicit: !!opts.explicit, emptyCode: opts.emptyCode, hasDefault: ("default" in opts), def: opts.default,
181
117
  defaultCode: opts.defaultCode };
182
118
  }
183
- // trailing: the [minTag..maxTag] optional context fields, each at most once in
184
- // strictly-increasing tag order (the tbs issuerUniqueID[1]/subjectUniqueID[2]/
185
- // extensions[3] block). members: [{ tag, name, schema, explicit? }].
186
119
  function trailing(members, opts) {
187
120
  opts = opts || {};
188
121
  return { fkind: "trailing", members: members, minTag: opts.minTag, maxTag: opts.maxTag,
189
122
  unexpectedCode: opts.unexpectedCode, orderCode: opts.orderCode };
190
123
  }
191
124
 
192
- // ---- structural combinators -----------------------------------------
193
125
 
194
126
  function seq(fields, opts) {
195
127
  opts = opts || {};
@@ -197,9 +129,6 @@ function seq(fields, opts) {
197
129
  code: opts.code, what: opts.what, build: opts.build, checks: opts.checks || [] };
198
130
  }
199
131
 
200
- // A NON-optional EXPLICIT context wrapper (CMS ContentInfo; the tbs [3] uses it
201
- // inside `trailing`). Asserts context class + tag, constructed, >=1 child, then
202
- // walks the inner schema on children[0].
203
132
  function explicit(tag, schema, opts) {
204
133
  opts = opts || {};
205
134
  return { kind: "explicit", tag: tag, schema: schema, emptyCode: opts.emptyCode, code: opts.code, what: opts.what };
@@ -225,19 +154,12 @@ function setOf(item, opts) {
225
154
  function setOfUnique(item, keyFn, opts) {
226
155
  return setOf(item, Object.assign({ unique: keyFn }, opts || {}));
227
156
  }
228
- // [tag] IMPLICIT SET OF item: the context tag replaces the universal SET tag,
229
- // so the node is a context-class constructed [tag] whose direct children are the
230
- // items (RFC 2986 sec. 4.1 CSR attributes). No inner SET, no EXPLICIT unwrap.
231
157
  function implicitSetOf(tag, item, opts) {
232
158
  opts = opts || {};
233
159
  return { kind: "repeat", item: item, assert: "implicit", implicitTag: tag, derSetOrder: true, code: opts.code, what: opts.what,
234
160
  min: opts.min, max: opts.max, maxCode: opts.maxCode,
235
161
  unique: opts.unique, dupCode: opts.dupCode, build: opts.build };
236
162
  }
237
- // [tag] IMPLICIT SEQUENCE OF item: the context tag replaces the universal SEQUENCE
238
- // tag, so the node is a context-class constructed [tag] whose direct children are the
239
- // items. Order-preserving: the SEQUENCE-OF sibling of implicitSetOf without the SET
240
- // ascending-DER-order rule (RFC 3161 extensions [1] IMPLICIT Extensions).
241
163
  function implicitSeqOf(tag, item, opts) {
242
164
  opts = opts || {};
243
165
  return { kind: "repeat", item: item, assert: "implicit", implicitTag: tag, code: opts.code, what: opts.what,
@@ -245,7 +167,6 @@ function implicitSeqOf(tag, item, opts) {
245
167
  unique: opts.unique, dupCode: opts.dupCode, build: opts.build };
246
168
  }
247
169
 
248
- // ---- the walk engine -------------------------------------------------
249
170
 
250
171
  /**
251
172
  * @primitive pki.schema.engine.walk
@@ -293,9 +214,6 @@ function walk(schema, node, ctx) {
293
214
  return undefined;
294
215
  }
295
216
 
296
- // An EXPLICIT [tag] wrapper carries EXACTLY ONE inner value; 0 children is
297
- // empty and 2+ would silently drop all but the first (the same drop-extra
298
- // fail-open the seq guard closes). Assert exactly one, return it.
299
217
  function _explicitInner(node, tag, ctx, code) {
300
218
  if (!node.children || node.children.length !== 1) {
301
219
  _fail(ctx, code, "EXPLICIT [" + tag + "] must wrap exactly one value");
@@ -326,18 +244,9 @@ function _walkRepeat(schema, node, ctx) {
326
244
  if (schema.min != null && kids.length < schema.min) {
327
245
  _fail(ctx, schema.code, (schema.what || "value") + " must contain at least " + schema.min + " element(s)");
328
246
  }
329
- // The element-count ceiling: a container of a great many tiny elements
330
- // amplifies memory through per-element walk products, so a schema that
331
- // parses attacker-sized lists declares `max` and fails typed instead.
332
247
  if (schema.max != null && kids.length > schema.max) {
333
248
  _fail(ctx, schema.maxCode || schema.code, (schema.what || "value") + " exceeds the element cap " + schema.max);
334
249
  }
335
- // DER (X.690 sec. 11.6) -- the components of a SET OF appear in ascending order, the
336
- // encodings compared as octet strings. SEQUENCE OF is order-preserving and is
337
- // exempt (no derSetOrder). Compare full TLV byte strings, the same canonical
338
- // order build.set emits, so a decode round-trips a build. Equal-adjacent
339
- // encodings are permitted here (semantic uniqueness is the `unique` option's
340
- // job); only a descending pair is non-canonical.
341
250
  if (schema.derSetOrder) {
342
251
  for (var s = 1; s < kids.length; s++) {
343
252
  if (Buffer.compare(kids[s - 1].bytes, kids[s].bytes) > 0) {
@@ -348,8 +257,6 @@ function _walkRepeat(schema, node, ctx) {
348
257
  var items = [];
349
258
  var seen = schema.unique ? new Set() : null;
350
259
  for (var i = 0; i < kids.length; i++) {
351
- // The item wrapper is the SAME shape unique() and build() see: { node,
352
- // value: <walk result> }. keyFn reads off item.value just like build does.
353
260
  var item = { node: kids[i], value: walk(schema.item, kids[i], ctx) };
354
261
  if (seen) {
355
262
  var key = schema.unique(item);
@@ -363,10 +270,6 @@ function _walkRepeat(schema, node, ctx) {
363
270
  return match;
364
271
  }
365
272
 
366
- // The walked-value <-> DEFAULT comparison behind the defaultCode reject: strict
367
- // equality for the leaf value domains (BigInt, number, string, boolean), byte
368
- // equality for Buffers. A format opting in declares its `default` in the same
369
- // domain its leaf's read yields.
370
273
  function _equalsDefault(value, def) {
371
274
  if (Buffer.isBuffer(value) && Buffer.isBuffer(def)) return value.equals(def);
372
275
  return value === def;
@@ -393,9 +296,6 @@ function _walkSeq(schema, node, ctx) {
393
296
  inner = _explicitInner(next, fld.tag, ctx, fld.emptyCode || schema.code);
394
297
  }
395
298
  var val = walk(fld.schema, inner, ctx);
396
- // X.690 sec. 11.5 -- DER: a component equal to its DEFAULT value shall not
397
- // be included in the encoding. Opt-in via defaultCode so the reject
398
- // stays in the format's own error-code family.
399
299
  if (fld.defaultCode != null && fld.hasDefault && _equalsDefault(val, fld.def)) {
400
300
  _fail(ctx, fld.defaultCode, "field " + JSON.stringify(fld.name) + " explicitly encodes its DEFAULT value (X.690 sec. 11.5)");
401
301
  }
@@ -407,17 +307,10 @@ function _walkSeq(schema, node, ctx) {
407
307
  _consumeTrailing(fld, kids, idx, fields, ctx);
408
308
  idx = kids.length;
409
309
  } else {
410
- // A malformed field descriptor is the same authoring fault as an
411
- // unknown schema.kind (walk's default case): fail loud instead of
412
- // silently skipping the descriptor -- a skipped field never binds and
413
- // under-specifies the sequence.
414
310
  _fail(ctx, (ctx.prefix || "schema") + "/bad-schema", "unknown field kind " + JSON.stringify(fld && fld.fkind));
415
311
  }
416
312
  }
417
313
 
418
- // Every child must be consumed by a field. A leftover element (no trailing
419
- // field ran to absorb it) is malformed -- dropping it silently would let a
420
- // closed sequence of optional fields accept a duplicate/extra element.
421
314
  if (idx < kids.length) {
422
315
  _fail(ctx, schema.code, (schema.what || "value") + " has an unexpected element after its last field");
423
316
  }
@@ -431,10 +324,6 @@ function _walkSeq(schema, node, ctx) {
431
324
  function _consumeTrailing(fld, kids, start, fields, ctx) {
432
325
  var byTag = {};
433
326
  for (var m = 0; m < fld.members.length; m++) byTag[fld.members[m].tag] = fld.members[m];
434
- // The monotonic-order sentinel must start below the lowest accepted tag.
435
- // Context tag numbers are non-negative, so -1 is below any member tag when
436
- // minTag is absent -- otherwise a trailing block whose first member is [0]
437
- // would reject that field (0 <= last==0) as repeated/out-of-order.
438
327
  var last = fld.minTag != null ? fld.minTag - 1 : -1;
439
328
  for (var i = start; i < kids.length; i++) {
440
329
  var t = kids[i];
@@ -455,14 +344,6 @@ function _consumeTrailing(fld, kids, start, fields, ctx) {
455
344
  }
456
345
  }
457
346
 
458
- // ---- the encode engine (the inverse of walk) -------------------------
459
- // encode(schema, value) is the constructor direction of the SAME schema walk
460
- // decodes: it interprets the schema against a plain structural value and emits
461
- // canonical DER. A single schema definition therefore drives both directions, so
462
- // context-tag (EXPLICIT/IMPLICIT) handling cannot diverge between them -- the class
463
- // of bug where a decoder reads a [tag] IMPLICIT field but an ad-hoc encoder emits
464
- // the wrong tag is structurally retired. Encode errors are authoring faults (a bad
465
- // value / an un-encodable schema), thrown as plain Errors, not parse verdicts.
466
347
 
467
348
  function _encFail(message) { throw new Error("schema.encode: " + message); }
468
349
 
@@ -505,8 +386,6 @@ function _wrapConstructed(schema, parts) {
505
386
  if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag, Buffer.concat(parts));
506
387
  var mode = schema.assert || "sequence";
507
388
  if (mode === "set") return asn1.build.set(parts);
508
- // "constructed" is a DECODE-time leniency (accept any constructed shape); the
509
- // canonical encoding is a universal SEQUENCE, same as "sequence".
510
389
  if (mode === "sequence" || mode === "constructed") return asn1.build.sequence(parts);
511
390
  _encFail("cannot encode a seq/repeat with assert " + JSON.stringify(mode));
512
391
  return undefined;
@@ -524,16 +403,11 @@ function _encodeSeq(schema, value, ctx) {
524
403
  } else if (fld.fkind === "optional") {
525
404
  if (_present(value[fld.name])) {
526
405
  var enc = encode(fld.schema, value[fld.name], ctx);
527
- // X.690 sec. 11.5 -- DER: a component equal to its DEFAULT value shall not
528
- // be included in the encoding. Compare canonical field encodings, so
529
- // encode never emits the non-canonical explicit-default form (which a
530
- // walk-side defaultCode reject would refuse to round-trip).
531
406
  var isDefault = fld.hasDefault && fld.def !== undefined &&
532
407
  enc.equals(encode(fld.schema, fld.def, ctx));
533
408
  if (!isDefault) parts.push(fld.explicit ? asn1.build.explicit(fld.tag, enc) : enc);
534
409
  }
535
410
  } else if (fld.fkind === "trailing") {
536
- // Emit present members in strictly-increasing tag order (the walk's rule).
537
411
  var members = fld.members.slice().sort(function (a, b) { return a.tag - b.tag; });
538
412
  for (var i = 0; i < members.length; i++) {
539
413
  var mm = members[i];
@@ -543,8 +417,6 @@ function _encodeSeq(schema, value, ctx) {
543
417
  }
544
418
  }
545
419
  } else {
546
- // The mirror of _walkSeq's unknown-field-kind reject: a malformed
547
- // descriptor is an authoring fault on the encode direction too.
548
420
  _encFail("unknown field kind " + JSON.stringify(fld && fld.fkind));
549
421
  }
550
422
  }
@@ -553,10 +425,6 @@ function _encodeSeq(schema, value, ctx) {
553
425
 
554
426
  function _encodeRepeat(schema, items, ctx) {
555
427
  if (!Array.isArray(items)) _encFail("a repeat value must be an array");
556
- // Enforce the SAME constraints walk enforces, so encode never emits DER its own
557
- // decoder rejects (the walk(decode(encode)) invariant): the SIZE minimum, and
558
- // semantic uniqueness (the key computed exactly as walk does, off the round-tripped
559
- // item -- a duplicate is an authoring fault, not a parse verdict).
560
428
  if (schema.min != null && items.length < schema.min) {
561
429
  _encFail("this repeat requires at least " + schema.min + " element(s) but got " + items.length);
562
430
  }
@@ -580,9 +448,6 @@ function _encodeRepeat(schema, items, ctx) {
580
448
  }
581
449
 
582
450
  function _encodeChoice(schema, value, ctx) {
583
- // Number.isInteger: a NaN / fractional arm passes a `< 0 || >= length` range
584
- // check (both compares are false for NaN) into an undefined alts lookup --
585
- // the same authoring fault as an out-of-range arm, failed the same way.
586
451
  if (!value || !Number.isInteger(value.arm) || value.arm < 0 || value.arm >= schema.alts.length) {
587
452
  _encFail("a choice value must be { arm: <index>, value: <arm value> }");
588
453
  }
@@ -641,19 +506,6 @@ function embeddedDer(schema, bytes, ctx, opts) {
641
506
  return walk(schema, node, ctx);
642
507
  }
643
508
 
644
- // X.690 sec. 11.2.2 -- a NamedBitList BIT STRING (KeyUsage, PKIFailureInfo, and the
645
- // like) MUST drop every trailing zero bit under DER, giving one canonical
646
- // encoding per value: an empty value carries 0 unused bits; a non-empty value's
647
- // last content octet is non-zero AND its lowest USED bit (at position
648
- // `unusedBits`) is set. `fail(message)` throws the caller's typed domain error,
649
- // so the reject code stays per-format. Centralized so no format re-derives -- and
650
- // silently diverges on -- the minimal-encoding rule (a DER-canonicalization
651
- // bypass class); see the named-bitlist-minimal-encoding-inlined gate.
652
- // ASN.1 node tag predicates -- the per-node `tagClass`/`tagNumber` test every
653
- // format's matches() detector (and the engine's own optional/choice walkers)
654
- // would otherwise re-inline. Centralized so a detector composes one predicate
655
- // instead of hand-rolling the comparison (and drifting); see the
656
- // detector-reinlines-root-tag-guard gate.
657
509
  function isUniversal(node, tagNumber) {
658
510
  return !!node && node.tagClass === "universal" && node.tagNumber === tagNumber;
659
511
  }
@@ -681,17 +533,13 @@ function assertMinimalNamedBits(unusedBits, bytes, fail) {
681
533
  }
682
534
 
683
535
  module.exports = {
684
- // structural
685
536
  seq: seq, field: field, optional: optional, explicit: explicit, trailing: trailing,
686
537
  seqOf: seqOf, setOf: setOf, setOfUnique: setOfUnique, implicitSetOf: implicitSetOf, implicitSeqOf: implicitSeqOf, choice: choice,
687
- // leaves
688
538
  oidLeaf: oidLeaf, integerLeaf: integerLeaf, boolean: boolean, octetString: octetString,
689
539
  bitString: bitString, implicitBitString: implicitBitString, implicitOctetString: implicitOctetString,
690
540
  implicitNull: implicitNull, implicitInteger: implicitInteger, implicitBoolean: implicitBoolean,
691
541
  any: any, decode: decode, time: time,
692
- // engine
693
542
  walk: walk, encode: encode, embeddedDer: embeddedDer, assertMinimalNamedBits: assertMinimalNamedBits,
694
- // node tag predicates
695
543
  isUniversal: isUniversal, isContext: isContext,
696
544
  isUniversalOneOf: isUniversalOneOf, isContextOneOf: isContextOneOf, isContextInRange: isContextInRange,
697
545
  };