@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/attrcert-verify.js
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) blamejs contributors
|
|
3
3
|
"use strict";
|
|
4
|
-
//
|
|
5
|
-
// @internal -- the RFC 5755 attribute-certificate signature seam, shared by pki.attrcert.verify and
|
|
6
|
-
// by any path that accepts an inbound AC. The slot, the wiring assertion and the octet-alignment
|
|
7
|
-
// refusal are the shared seam (lib/verify-seam.js); what is domain-specific is the error class and
|
|
8
|
-
// the byte range the signature covers. It is not wired into index.js and is reached only by require.
|
|
4
|
+
// @internal
|
|
9
5
|
|
|
10
6
|
var frameworkError = require("./framework-error");
|
|
11
7
|
var seam = require("./verify-seam");
|
|
12
8
|
|
|
13
9
|
var _seam = seam.makeSeam("attrcert-verify", frameworkError.AttrCertError, "attrcert/bad-input");
|
|
14
10
|
|
|
15
|
-
// Verify a parsed attribute certificate's signature over its exact AttributeCertificateInfo bytes
|
|
16
|
-
// under the AC issuer's SubjectPublicKeyInfo DER (RFC 5755 sec. 5, item 2).
|
|
17
11
|
function verifyAcSignature(ac, spkiBytes) {
|
|
18
12
|
return _seam.verify(ac.signatureAlgorithm, ac.signatureValue, spkiBytes, ac.tbsBytes);
|
|
19
13
|
}
|
package/lib/byte-reader.js
CHANGED
|
@@ -17,9 +17,6 @@
|
|
|
17
17
|
* offset walk in a format module.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
// A bounded cursor over `buf[start, end)`, faulting through the caller's ErrorClass
|
|
21
|
-
// `E` (constructed `new E(code, message)`). `defaultCode` is the fault code used
|
|
22
|
-
// when a read is not given its own.
|
|
23
20
|
function ByteReader(buf, start, end, E, defaultCode) {
|
|
24
21
|
if (!Buffer.isBuffer(buf)) throw new TypeError("ByteReader: buf must be a Buffer");
|
|
25
22
|
this.buf = buf;
|
|
@@ -42,14 +39,10 @@ ByteReader.prototype.u24 = function (code) {
|
|
|
42
39
|
};
|
|
43
40
|
ByteReader.prototype.u32 = function (code) { this._need(4, code); var v = this.buf.readUInt32BE(this.pos); this.pos += 4; return v; };
|
|
44
41
|
ByteReader.prototype.u64 = function (code) { this._need(8, code); var v = this.buf.readBigUInt64BE(this.pos); this.pos += 8; return v; };
|
|
45
|
-
// A fixed-width opaque slice (zero-copy view into the backing buffer).
|
|
46
42
|
ByteReader.prototype.fixed = function (n, code) {
|
|
47
43
|
this._need(n, code);
|
|
48
44
|
var s = this.buf.subarray(this.pos, this.pos + n); this.pos += n; return s;
|
|
49
45
|
};
|
|
50
|
-
// opaque<min..max> is a length-prefixed vector (lenWidth-byte big-endian prefix:
|
|
51
|
-
// 2 or 3). The length prefix itself is a plain read (a truncation there is the
|
|
52
|
-
// default code); only a lying length whose body overruns the bound carries `code`.
|
|
53
46
|
ByteReader.prototype.vector = function (lenWidth, min, max, code) {
|
|
54
47
|
var len = lenWidth === 3 ? this.u24() : this.u16();
|
|
55
48
|
if (len < min) throw new this.E(code, "vector length " + len + " below minimum " + min);
|
|
@@ -57,7 +50,6 @@ ByteReader.prototype.vector = function (lenWidth, min, max, code) {
|
|
|
57
50
|
this._need(len, code);
|
|
58
51
|
var s = this.buf.subarray(this.pos, this.pos + len); this.pos += len; return s;
|
|
59
52
|
};
|
|
60
|
-
// A bounded child cursor over the next `len` bytes, sharing the same ErrorClass.
|
|
61
53
|
ByteReader.prototype.subReader = function (len, code) {
|
|
62
54
|
this._need(len, code);
|
|
63
55
|
var r = new ByteReader(this.buf, this.pos, this.pos + len, this.E, this.defaultCode); this.pos += len; return r;
|
package/lib/byte-writer.js
CHANGED
|
@@ -18,9 +18,6 @@
|
|
|
18
18
|
* in a format module.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
// A growable big-endian sink, faulting through the caller's ErrorClass `E`
|
|
22
|
-
// (constructed `new E(code, message)`). `defaultCode` is the fault code used when a
|
|
23
|
-
// write is not given its own.
|
|
24
21
|
function ByteWriter(E, defaultCode) {
|
|
25
22
|
this.parts = [];
|
|
26
23
|
this.len = 0;
|
|
@@ -28,9 +25,6 @@ function ByteWriter(E, defaultCode) {
|
|
|
28
25
|
this.defaultCode = defaultCode || "byte-writer/bad-value";
|
|
29
26
|
}
|
|
30
27
|
ByteWriter.prototype._push = function (buf) { this.parts.push(buf); this.len += buf.length; };
|
|
31
|
-
// A non-negative integer that fills exactly `width` big-endian octets; the width MUST be 1..4 (a wider
|
|
32
|
-
// or malformed width would break the max computation via 32-bit shift wrap-around and mis-size the
|
|
33
|
-
// field), and a value outside [0, 2^(8*width)-1] (or a non-integer) faults instead of silently wrapping.
|
|
34
28
|
ByteWriter.prototype._uint = function (v, width, code) {
|
|
35
29
|
if (!Number.isInteger(width) || width < 1 || width > 4) throw new this.E(code || this.defaultCode, "an integer width must be 1..4, got " + width);
|
|
36
30
|
var max = width === 4 ? 0xffffffff : (1 << (8 * width)) - 1;
|
|
@@ -43,7 +37,6 @@ ByteWriter.prototype.u8 = function (v, code) { this._uint(v, 1, code); return th
|
|
|
43
37
|
ByteWriter.prototype.u16 = function (v, code) { this._uint(v, 2, code); return this; };
|
|
44
38
|
ByteWriter.prototype.u24 = function (v, code) { this._uint(v, 3, code); return this; };
|
|
45
39
|
ByteWriter.prototype.u32 = function (v, code) { this._uint(v, 4, code); return this; };
|
|
46
|
-
// A uint64 from a BigInt or a safe-integer Number; refused if out of [0, 2^64-1].
|
|
47
40
|
ByteWriter.prototype.u64 = function (v, code) {
|
|
48
41
|
var big;
|
|
49
42
|
if (typeof v === "bigint") big = v;
|
|
@@ -53,14 +46,10 @@ ByteWriter.prototype.u64 = function (v, code) {
|
|
|
53
46
|
var b = Buffer.alloc(8); b.writeBigUInt64BE(big); this._push(b);
|
|
54
47
|
return this;
|
|
55
48
|
};
|
|
56
|
-
// Append a raw opaque slice verbatim (a fixed-width field).
|
|
57
49
|
ByteWriter.prototype.bytes = function (buf, code) {
|
|
58
50
|
if (!Buffer.isBuffer(buf)) throw new this.E(code || this.defaultCode, "bytes() requires a Buffer");
|
|
59
51
|
this._push(buf); return this;
|
|
60
52
|
};
|
|
61
|
-
// opaque<min..max> -- a `lenWidth`-byte big-endian length prefix (1..4) then `body`.
|
|
62
|
-
// The body length is bounded [min, max] before the prefix is written, so an over-long
|
|
63
|
-
// body cannot emit a prefix that disagrees with what follows.
|
|
64
53
|
ByteWriter.prototype.vector = function (lenWidth, min, max, body, code) {
|
|
65
54
|
if (!Buffer.isBuffer(body)) throw new this.E(code || this.defaultCode, "vector() body must be a Buffer");
|
|
66
55
|
if (body.length < min) throw new this.E(code || this.defaultCode, "vector body " + body.length + " below minimum " + min);
|
package/lib/cbor-det.js
CHANGED
|
@@ -43,30 +43,17 @@ var guard = require("./guard-all");
|
|
|
43
43
|
|
|
44
44
|
var CborError = frameworkError.CborError;
|
|
45
45
|
|
|
46
|
-
// Reusable little-work scratch for IEEE-754 float decode + the shortest-form
|
|
47
|
-
// round-trip checks. Single-threaded synchronous use, reset on every write.
|
|
48
46
|
var _fbuf = new ArrayBuffer(8);
|
|
49
47
|
var _fdv = new DataView(_fbuf);
|
|
50
48
|
|
|
51
|
-
// Strict UTF-8 validator (fatal); a lone continuation / truncated sequence
|
|
52
|
-
// throws instead of substituting U+FFFD, which is the fail-open class the
|
|
53
|
-
// toolkit refuses. This mirrors asn1-der's strict text decode.
|
|
54
49
|
var _utf8 = new TextDecoder("utf-8", { fatal: true });
|
|
55
50
|
|
|
56
|
-
// The ECMAScript Date-valid window is +/- 8,640,000,000,000,000 ms; in seconds
|
|
57
|
-
// that is +/- 8.64e12. read.time bounds an epoch value to this window before
|
|
58
|
-
// narrowing the BigInt to a Number, so the narrowing is lossless (well under
|
|
59
|
-
// 2^53) and the millisecond result stays a safe integer.
|
|
60
51
|
var _MAX_EPOCH_SECONDS = 8640000000000n;
|
|
61
52
|
|
|
62
53
|
function _asBuffer(input, who) {
|
|
63
54
|
return guard.bytes.view(input, CborError, "cbor/not-buffer", who);
|
|
64
55
|
}
|
|
65
56
|
|
|
66
|
-
// Determinism profile -> a ruleset. v1 whitelists only "deterministic"
|
|
67
|
-
// (RFC 8949 sec. 4.2 core); an unknown profile is a config-time TypeError, so
|
|
68
|
-
// there is no path to a lenient decode. A future "ctap2" (length-first map
|
|
69
|
-
// ordering) is a data row here, not a switch through the decoder.
|
|
70
57
|
function _profile(name) {
|
|
71
58
|
var p = name === undefined ? "deterministic" : name;
|
|
72
59
|
if (p === "deterministic") return { mapKeyCompare: Buffer.compare };
|
|
@@ -81,28 +68,21 @@ function _assertUtf8(buf) {
|
|
|
81
68
|
}
|
|
82
69
|
}
|
|
83
70
|
|
|
84
|
-
// Decode the raw IEEE-754 bits (carried in the argument) to a JS double, per
|
|
85
|
-
// the additional-info width: 25 half, 26 single, 27 double.
|
|
86
71
|
function _readFloatBits(argument, ai) {
|
|
87
72
|
if (ai === 25) { _fdv.setUint16(0, Number(argument)); return _fdv.getFloat16(0); }
|
|
88
73
|
if (ai === 26) { _fdv.setUint32(0, Number(argument)); return _fdv.getFloat32(0); }
|
|
89
74
|
_fdv.setBigUint64(0, argument); return _fdv.getFloat64(0);
|
|
90
75
|
}
|
|
91
76
|
|
|
92
|
-
// Is d exactly representable as a half float? (round-trip through float16;
|
|
93
|
-
// Object.is keeps -0 and the NaN/Inf cases honest).
|
|
94
77
|
function _halfRoundtrips(d) {
|
|
95
78
|
_fdv.setFloat16(0, d);
|
|
96
79
|
return Object.is(_fdv.getFloat16(0), d);
|
|
97
80
|
}
|
|
98
81
|
|
|
99
|
-
// Is d exactly representable as a single float?
|
|
100
82
|
function _singleRoundtrips(d) {
|
|
101
83
|
return Object.is(Math.fround(d), d);
|
|
102
84
|
}
|
|
103
85
|
|
|
104
|
-
// Recursive-descent decode of one CBOR item over [start, limit): fail-closed,
|
|
105
|
-
// depth-budgeted, zero-copy. Mirrors asn1-der's _decodeTLV.
|
|
106
86
|
function _decodeItem(buf, start, limit, depth, maxD, rules, state) {
|
|
107
87
|
if (depth > maxD) throw new CborError("cbor/too-deep", "nesting exceeds depth cap " + maxD);
|
|
108
88
|
state.n += 1;
|
|
@@ -113,7 +93,6 @@ function _decodeItem(buf, start, limit, depth, maxD, rules, state) {
|
|
|
113
93
|
var mt = ib >> 5;
|
|
114
94
|
var ai = ib & 0x1f;
|
|
115
95
|
|
|
116
|
-
// Head well-formedness, before reading the argument.
|
|
117
96
|
if (ib === 0xff) throw new CborError("cbor/unexpected-break", "stray break byte (0xff) at an item head");
|
|
118
97
|
if (ai === 28 || ai === 29 || ai === 30) throw new CborError("cbor/reserved-ai", "reserved additional-info " + ai);
|
|
119
98
|
if (ai === 31) {
|
|
@@ -123,7 +102,6 @@ function _decodeItem(buf, start, limit, depth, maxD, rules, state) {
|
|
|
123
102
|
throw new CborError("cbor/reserved-ai", "additional-info 31 is undefined for major type " + mt);
|
|
124
103
|
}
|
|
125
104
|
|
|
126
|
-
// The argument, minimal-checked, as a lossless BigInt.
|
|
127
105
|
var argument;
|
|
128
106
|
var contentStart;
|
|
129
107
|
if (ai <= 23) {
|
|
@@ -137,9 +115,6 @@ function _decodeItem(buf, start, limit, depth, maxD, rules, state) {
|
|
|
137
115
|
else if (nBytes === 4) argument = BigInt(buf.readUInt32BE(p));
|
|
138
116
|
else argument = buf.readBigUInt64BE(p);
|
|
139
117
|
p += nBytes;
|
|
140
|
-
// Preferred (shortest) argument, required for every major type but 7. In
|
|
141
|
-
// type 7 the "argument" is raw float bits, governed by the shortest-float
|
|
142
|
-
// rule.
|
|
143
118
|
if (mt !== 7) {
|
|
144
119
|
var minForWidth = nBytes === 1 ? 24n : nBytes === 2 ? 256n : nBytes === 4 ? 65536n : 4294967296n;
|
|
145
120
|
if (argument < minForWidth) {
|
|
@@ -191,7 +166,6 @@ function _decodeItem(buf, start, limit, depth, maxD, rules, state) {
|
|
|
191
166
|
children = [inner.node];
|
|
192
167
|
end = inner.end;
|
|
193
168
|
} else {
|
|
194
|
-
// mt === 7: simple value or float.
|
|
195
169
|
if (ai <= 23) {
|
|
196
170
|
end = contentStart;
|
|
197
171
|
} else if (ai === 24) {
|
|
@@ -281,7 +255,6 @@ function _expectMajor(node, mt, who) {
|
|
|
281
255
|
}
|
|
282
256
|
}
|
|
283
257
|
|
|
284
|
-
// Assert a tag node with a specific tag number, and return its one inner item.
|
|
285
258
|
function _tagInner(node, tagNum, who) {
|
|
286
259
|
if (!node || node.majorType !== 6 || node.argument !== BigInt(tagNum)) {
|
|
287
260
|
throw new CborError("cbor/unexpected-tag", who + ": expected tag " + tagNum);
|
|
@@ -615,8 +588,6 @@ function readTime(node) {
|
|
|
615
588
|
}
|
|
616
589
|
var ns = Number(secs);
|
|
617
590
|
var d = new Date(ns < 0 ? -constants.TIME.seconds(-ns) : constants.TIME.seconds(ns));
|
|
618
|
-
// Coverage residual -- the epoch-window bound above already rejects any value the
|
|
619
|
-
// Date constructor cannot represent, so this backstop is defense-in-depth.
|
|
620
591
|
if (isNaN(guard.time.instantOf(d))) throw new CborError("cbor/bad-time", "epoch time out of range");
|
|
621
592
|
return d;
|
|
622
593
|
}
|
|
@@ -644,33 +615,18 @@ function readOid(node) {
|
|
|
644
615
|
return asn1.decodeOidContent(inner.content);
|
|
645
616
|
}
|
|
646
617
|
|
|
647
|
-
// ---- deterministic-CBOR encoder (RFC 8949 sec. 4.2) -- the byte-exact inverse of decode ----
|
|
648
|
-
// Every emitted head is the shortest form (the exact mirror of decode's cbor/non-minimal-argument reject),
|
|
649
|
-
// every length is definite, and map keys are sorted bytewise + unique -- so decode(build.x(...)) round-trips
|
|
650
|
-
// or the builder produced a shape its own strict decoder rejects. Nested items are pre-encoded CBOR item
|
|
651
|
-
// Buffers (the asn1.build pattern); the CBOR-encoded PKI surfaces (C509, COSE) compose these leaves.
|
|
652
618
|
function _cbItem(x, who) {
|
|
653
619
|
if (!Buffer.isBuffer(x)) throw new CborError("cbor/not-buffer", who + ": expected a pre-encoded CBOR item Buffer");
|
|
654
620
|
return x;
|
|
655
621
|
}
|
|
656
|
-
// Validate an assembled container decodes: well-formed nested items (no malformed head, indefinite length,
|
|
657
|
-
// stray break, or trailing bytes), AND within the decoder's depth cap -- a container adds ONE nesting
|
|
658
|
-
// level, so a child AT the cap would overflow the output. Decoding the whole output in one pass catches
|
|
659
|
-
// both, so the encoder never produces bytes its own strict decoder rejects.
|
|
660
622
|
function _assertDecodes(out, who) {
|
|
661
623
|
try { decode(out); } catch (e) { throw new CborError("cbor/bad-item", who + ": produced bytes the strict decoder rejects (" + (e && e.code) + ")", e); }
|
|
662
624
|
return out;
|
|
663
625
|
}
|
|
664
|
-
// Mirror the decoder's total-size cap (constants.LIMITS.CBOR_MAX_BYTES) so a string leaf never emits an
|
|
665
|
-
// item the strict reader would reject as too large -- the encode/decode round trip stays closed under the
|
|
666
|
-
// default limits.
|
|
667
626
|
function _capString(out, who) {
|
|
668
627
|
if (out.length > constants.LIMITS.CBOR_MAX_BYTES) throw new CborError("cbor/too-large", who + ": encoded " + out.length + " bytes exceeds cap " + constants.LIMITS.CBOR_MAX_BYTES);
|
|
669
628
|
return out;
|
|
670
629
|
}
|
|
671
|
-
// Reject a JS string carrying an unpaired UTF-16 surrogate: Buffer.from(..., "utf8") would silently
|
|
672
|
-
// substitute U+FFFD, so the emitted text string would not be the input (and read.text enforces well-formed
|
|
673
|
-
// UTF-8). Fail closed to match the decoder rather than corrupt the text.
|
|
674
630
|
function _assertWellFormedText(str, who) {
|
|
675
631
|
for (var i = 0; i < str.length; i++) {
|
|
676
632
|
var c = str.charCodeAt(i);
|
|
@@ -678,7 +634,6 @@ function _assertWellFormedText(str, who) {
|
|
|
678
634
|
else if (c >= 0xdc00 && c <= 0xdfff) throw new CborError("cbor/bad-utf8", who + ": the string has an unpaired low surrogate");
|
|
679
635
|
}
|
|
680
636
|
}
|
|
681
|
-
// The initial byte + minimal-width argument for major type `mt` and unsigned `argument`.
|
|
682
637
|
function _head(mt, argument, who) {
|
|
683
638
|
var a = typeof argument === "bigint" ? argument : BigInt(argument);
|
|
684
639
|
if (a < 0n) throw new CborError("cbor/bad-argument", who + ": a CBOR head argument must be non-negative");
|
|
@@ -704,10 +659,6 @@ var build = {
|
|
|
704
659
|
map: function (pairs) {
|
|
705
660
|
if (!Array.isArray(pairs)) throw new CborError("cbor/bad-argument", "build.map: expected an array of [key, value] pairs");
|
|
706
661
|
var enc = pairs.map(function (p, i) { if (!Array.isArray(p) || p.length !== 2) throw new CborError("cbor/bad-argument", "build.map[" + i + "]: each entry is a [key, value] pair"); return [_cbItem(p[0], "build.map key"), _cbItem(p[1], "build.map value")]; });
|
|
707
|
-
// RFC 8949 sec. 4.2.1 Core Deterministic: keys sorted in the BYTEWISE lexicographic order of their
|
|
708
|
-
// encodings -- NOT the length-first order of sec. 4.2.3 (the older RFC 7049 "Canonical CBOR" variant).
|
|
709
|
-
// This MUST match the decoder, which enforces bytewise order (_profile "deterministic" -> Buffer.compare
|
|
710
|
-
// at :70); a length-first sort here would emit a map the strict decoder then rejects as unsorted.
|
|
711
662
|
enc.sort(function (a, b) { return Buffer.compare(a[0], b[0]); });
|
|
712
663
|
for (var i = 1; i < enc.length; i++) { if (Buffer.compare(enc[i - 1][0], enc[i][0]) === 0) throw new CborError("cbor/duplicate-map-key", "build.map: duplicate map key"); }
|
|
713
664
|
var flat = [_head(5, pairs.length, "build.map")];
|
|
@@ -718,14 +669,12 @@ var build = {
|
|
|
718
669
|
boolean: function (v) { return Buffer.from([v ? 0xf5 : 0xf4]); },
|
|
719
670
|
nullValue: function () { return Buffer.from([0xf6]); },
|
|
720
671
|
raw: function (buf) { return _assertDecodes(_asBuffer(buf, "build.raw"), "build.raw"); },
|
|
721
|
-
// Tagged leaves -- the inverse of read.biguint / read.time / read.oid.
|
|
722
672
|
biguint: function (n) {
|
|
723
673
|
var a = typeof n === "bigint" ? n : BigInt(n);
|
|
724
674
|
if (a < 0n) throw new CborError("cbor/bad-argument", "build.biguint: value must be non-negative");
|
|
725
675
|
var hex = a.toString(16); if (hex.length % 2) hex = "0" + hex;
|
|
726
676
|
var mag = a === 0n ? Buffer.alloc(0) : Buffer.from(hex, "hex");
|
|
727
677
|
if (mag.length <= 8) throw new CborError("cbor/bad-argument", "build.biguint: a value that fits 8 bytes must use build.uint (RFC 8949 preferred serialization)");
|
|
728
|
-
// Mirror read.biguint's cap so the tagged bignum builder never emits a value the strict reader rejects.
|
|
729
678
|
if (mag.length > constants.LIMITS.CBOR_MAX_BIGUINT_BYTES) throw new CborError("cbor/biguint-too-large", "build.biguint: " + mag.length + " bytes exceeds cap " + constants.LIMITS.CBOR_MAX_BIGUINT_BYTES);
|
|
730
679
|
return build.tag(2, build.byteString(mag));
|
|
731
680
|
},
|
|
@@ -734,12 +683,9 @@ var build = {
|
|
|
734
683
|
if (guard.time.isDate(v)) {
|
|
735
684
|
ms = guard.time.instantOf(v);
|
|
736
685
|
if (Number.isNaN(ms)) throw new CborError("cbor/bad-time", "build.time: an Invalid Date has no epoch value");
|
|
737
|
-
// read.time reads only an integer (second-granularity) tag-1, so a sub-second Date cannot round-trip:
|
|
738
|
-
// reject it rather than silently truncate the milliseconds.
|
|
739
686
|
if (ms % 1000 !== 0) throw new CborError("cbor/bad-time", "build.time: a Date with sub-second precision cannot be a second-granularity CBOR epoch; round to whole seconds");
|
|
740
687
|
}
|
|
741
688
|
var secs = guard.time.isDate(v) ? BigInt(Math.floor(ms / 1000)) : (typeof v === "bigint" ? v : BigInt(v));
|
|
742
|
-
// Mirror read.time's bound so build.time never emits a tag-1 the strict reader would reject as out of range.
|
|
743
689
|
if (secs < -_MAX_EPOCH_SECONDS || secs > _MAX_EPOCH_SECONDS) throw new CborError("cbor/bad-time", "build.time: epoch seconds " + secs + " are outside the representable Date range");
|
|
744
690
|
return build.tag(1, build.int(secs));
|
|
745
691
|
},
|