@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.
- package/CHANGELOG.md +22 -1
- package/README.md +1 -1
- package/index.js +1 -1
- package/lib/acme.js +59 -815
- package/lib/asn1-der.js +7 -245
- package/lib/attrcert-sign.js +12 -260
- package/lib/attrcert-verify.js +1 -7
- package/lib/byte-reader.js +0 -8
- package/lib/byte-writer.js +0 -11
- package/lib/cbor-det.js +0 -54
- package/lib/cmc-build.js +15 -357
- package/lib/cmc-verify.js +6 -239
- package/lib/cmp-build.js +41 -317
- package/lib/cmp-session.js +73 -760
- package/lib/cmp-verify.js +32 -488
- package/lib/cms-compress.js +3 -32
- package/lib/cms-decrypt.js +29 -294
- package/lib/cms-encrypt.js +14 -234
- package/lib/cms-sign.js +29 -324
- package/lib/cms-verify.js +9 -500
- package/lib/composite-kem.js +2 -102
- package/lib/composite-sig.js +1 -77
- package/lib/constants.js +0 -249
- package/lib/crl-sign.js +9 -237
- package/lib/crl-verify.js +1 -10
- package/lib/crmf-sign.js +19 -198
- package/lib/crmf-verify.js +1 -12
- package/lib/csr-sign.js +3 -34
- package/lib/csr-verify.js +1 -12
- package/lib/ct.js +28 -253
- package/lib/edwards-point.js +10 -44
- package/lib/est.js +28 -764
- package/lib/framework-error.js +4 -182
- package/lib/guard-all.js +1 -58
- package/lib/guard-async.js +1 -36
- package/lib/guard-bytes.js +6 -650
- package/lib/guard-compress.js +5 -102
- package/lib/guard-crypto.js +1 -40
- package/lib/guard-der.js +2 -93
- package/lib/guard-encoding.js +2 -60
- package/lib/guard-header.js +1 -36
- package/lib/guard-identifier.js +7 -531
- package/lib/guard-intrinsic.js +1 -150
- package/lib/guard-json.js +10 -73
- package/lib/guard-limits.js +1 -77
- package/lib/guard-list.js +1 -49
- package/lib/guard-name.js +3 -209
- package/lib/guard-parsed.js +7 -335
- package/lib/guard-range.js +1 -71
- package/lib/guard-secret.js +1 -102
- package/lib/guard-text.js +1 -64
- package/lib/guard-time.js +1 -97
- package/lib/hpke.js +3 -105
- package/lib/http-digest.js +14 -142
- package/lib/http-retry-after.js +1 -47
- package/lib/http-transport.js +21 -131
- package/lib/inspect.js +30 -284
- package/lib/ip-utils.js +6 -47
- package/lib/jose.js +7 -142
- package/lib/key.js +2 -67
- package/lib/lint.js +9 -194
- package/lib/merkle.js +1 -27
- package/lib/mime.js +9 -82
- package/lib/ocsp-request-verify.js +1 -14
- package/lib/ocsp-verify.js +1 -82
- package/lib/ocsp.js +11 -169
- package/lib/oid.js +5 -337
- package/lib/path-validate.js +103 -1492
- package/lib/pbes2.js +2 -89
- package/lib/pkcs12-build.js +31 -379
- package/lib/pki-build.js +64 -290
- package/lib/rc2.js +2 -18
- package/lib/rfc3339.js +4 -27
- package/lib/scep.js +59 -233
- package/lib/schema-all.js +0 -122
- package/lib/schema-attrcert.js +4 -146
- package/lib/schema-c509.js +153 -802
- package/lib/schema-cmc.js +5 -220
- package/lib/schema-cmp.js +2 -223
- package/lib/schema-cms.js +13 -427
- package/lib/schema-crl.js +5 -68
- package/lib/schema-crmf.js +6 -167
- package/lib/schema-csr.js +1 -54
- package/lib/schema-csrattrs.js +2 -87
- package/lib/schema-engine.js +0 -152
- package/lib/schema-ocsp.js +0 -117
- package/lib/schema-pkcs12.js +2 -93
- package/lib/schema-pkcs8.js +3 -35
- package/lib/schema-pkix.js +24 -655
- package/lib/schema-smime.js +0 -54
- package/lib/schema-tsp.js +3 -99
- package/lib/schema-x509.js +4 -63
- package/lib/shbs.js +11 -95
- package/lib/sign-scheme.js +2 -97
- package/lib/sigstore.js +9 -169
- package/lib/sleep.js +2 -8
- package/lib/smime.js +15 -408
- package/lib/tls-cert-compress.js +0 -62
- package/lib/trust.js +19 -185
- package/lib/tsp-sign.js +16 -270
- package/lib/validator-all.js +1 -30
- package/lib/validator-attcert.js +2 -46
- package/lib/validator-cose.js +2 -153
- package/lib/validator-keydesc.js +1 -37
- package/lib/validator-sig.js +1 -46
- package/lib/validator-tls.js +1 -88
- package/lib/validator-tpm.js +19 -122
- package/lib/verify-seam.js +1 -24
- package/lib/webauthn-mds.js +3 -400
- package/lib/webauthn.js +12 -833
- package/lib/webcrypto.js +5 -485
- package/lib/x509-sign.js +4 -108
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/schema-engine.js
CHANGED
|
@@ -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
|
};
|