@blamejs/pki 0.8.59 → 0.8.61
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 +57 -0
- package/lib/acme.js +15 -7
- package/lib/alt-sig.js +3 -1
- package/lib/asn1-der.js +82 -34
- package/lib/attrcert-sign.js +19 -16
- package/lib/byte-writer.js +63 -13
- package/lib/cbor-det.js +9 -3
- package/lib/cmc-build.js +26 -18
- package/lib/cmp-build.js +35 -33
- package/lib/cmp-session.js +19 -9
- package/lib/cms-decrypt.js +37 -23
- package/lib/cms-digest.js +2 -3
- package/lib/cms-encrypt.js +38 -33
- package/lib/cms-sign.js +65 -43
- package/lib/cms-verify.js +8 -4
- package/lib/composite-kem.js +28 -29
- package/lib/crl-sign.js +24 -17
- package/lib/crmf-sign.js +11 -17
- package/lib/csr-sign.js +5 -2
- package/lib/ct.js +38 -25
- package/lib/est.js +12 -9
- package/lib/guard-bytes.js +5 -1
- package/lib/guard-crypto.js +506 -14
- package/lib/guard-der.js +6 -1
- package/lib/guard-intrinsic.js +12 -4
- package/lib/guard-list.js +64 -0
- package/lib/guard-name.js +1 -1
- package/lib/guard-secret.js +3 -2
- package/lib/hpke.js +34 -27
- package/lib/http-digest.js +5 -7
- package/lib/http-transport.js +12 -3
- package/lib/inspect.js +10 -2
- package/lib/jose.js +3 -1
- package/lib/key.js +41 -29
- package/lib/lint.js +236 -152
- package/lib/mime.js +9 -5
- package/lib/ocsp.js +26 -24
- package/lib/path-validate.js +43 -13
- package/lib/pbes2.js +12 -9
- package/lib/pkcs11-uri.js +3 -1
- package/lib/pkcs12-build.js +19 -17
- package/lib/pki-build.js +17 -13
- package/lib/possession.js +3 -1
- package/lib/rc2.js +6 -2
- package/lib/revocation-fetch.js +78 -19
- package/lib/scep.js +21 -14
- package/lib/schema-attrcert.js +4 -2
- package/lib/schema-c509.js +94 -78
- package/lib/schema-cmc.js +5 -2
- package/lib/schema-cmp.js +6 -3
- package/lib/schema-cms.js +7 -4
- package/lib/schema-crl.js +1 -1
- package/lib/schema-crmf.js +1 -1
- package/lib/schema-csr.js +3 -3
- package/lib/schema-engine.js +36 -18
- package/lib/schema-pkcs1.js +7 -3
- package/lib/schema-pkcs12.js +9 -6
- package/lib/schema-pkix.js +19 -3
- package/lib/schema-sec1.js +4 -1
- package/lib/schema-tsp.js +7 -4
- package/lib/shbs.js +10 -9
- package/lib/sign-scheme.js +2 -2
- package/lib/sigstore.js +9 -9
- package/lib/smime.js +19 -16
- package/lib/tlog.js +20 -13
- package/lib/tuf.js +7 -4
- package/lib/validator-cose.js +2 -2
- package/lib/validator-keydesc.js +4 -1
- package/lib/validator-tls.js +7 -2
- package/lib/webauthn-mds.js +3 -7
- package/lib/webauthn.js +4 -11
- package/lib/webcrypto.js +70 -49
- package/lib/x509-sign.js +20 -15
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/schema-engine.js
CHANGED
|
@@ -98,7 +98,7 @@ function isResourceRefusal(e) {
|
|
|
98
98
|
function withResources(ns, source) {
|
|
99
99
|
if (!source || (source.caps == null && source.budget == null)) return ns;
|
|
100
100
|
var out = Object.create(null);
|
|
101
|
-
var keys =
|
|
101
|
+
var keys = intrinsic.keys(ns);
|
|
102
102
|
for (var i = 0; i < keys.length; i++) out[keys[i]] = ns[keys[i]];
|
|
103
103
|
out.caps = source.caps;
|
|
104
104
|
out.budget = source.budget;
|
|
@@ -146,11 +146,11 @@ function integerLeaf() { return { kind: "leaf", read: asn1.read.integer, writ
|
|
|
146
146
|
function boolean() { return { kind: "leaf", read: asn1.read.boolean, write: function (v) { return asn1.build.boolean(v); } }; }
|
|
147
147
|
function octetString() { return { kind: "leaf", read: asn1.read.octetString, write: function (v) { return asn1.build.octetString(v); } }; }
|
|
148
148
|
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); } }; }
|
|
149
|
-
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,
|
|
149
|
+
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, intrinsic.bufferConcat([intrinsic.bufferFrom([v.unusedBits]), v.bytes])); } }; }
|
|
150
150
|
function implicitOctetString(tag) { return { kind: "leaf", read: function (n) { return asn1.read.octetStringImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, v); } }; }
|
|
151
|
-
function implicitNull(tag) { return { kind: "leaf", read: function (n) { return asn1.read.nullImplicit(n, tag); }, write: function () { return asn1.build.contextPrimitive(tag,
|
|
151
|
+
function implicitNull(tag) { return { kind: "leaf", read: function (n) { return asn1.read.nullImplicit(n, tag); }, write: function () { return asn1.build.contextPrimitive(tag, intrinsic.bufferAlloc(0)); } }; }
|
|
152
152
|
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)); } }; }
|
|
153
|
-
function implicitBoolean(tag) { return { kind: "leaf", read: function (n) { return asn1.read.booleanImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag,
|
|
153
|
+
function implicitBoolean(tag) { return { kind: "leaf", read: function (n) { return asn1.read.booleanImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, intrinsic.bufferFrom([v ? 0xff : 0x00])); } }; }
|
|
154
154
|
function any() { return { kind: "any" }; }
|
|
155
155
|
function decode(fn, write) { return { kind: "decode", fn: fn, write: write }; }
|
|
156
156
|
|
|
@@ -328,7 +328,14 @@ function _walkRepeat(schema, node, ctx) {
|
|
|
328
328
|
if (seen.has(key)) _fail(ctx, schema.dupCode || schema.code, "duplicate element " + key);
|
|
329
329
|
seen.add(key);
|
|
330
330
|
}
|
|
331
|
-
|
|
331
|
+
/** @internal The element is APPENDED by defining its index. `push` stores, and a store walks the
|
|
332
|
+
* prototype chain for a setter, so an accessor at an array index received each element as the
|
|
333
|
+
* repeat was walked and left the list a hole that reads back whatever its getter answers.
|
|
334
|
+
* `m.items` is what every build() reads its elements out of, and a DN is a SEQUENCE OF RDN:
|
|
335
|
+
* measured, a certificate whose subject is `C=US, ST=California, O=blamejs pki, OU=Test,
|
|
336
|
+
* CN=pkijs.com` parsed with the accessor's value in place of its first RDN, and the parse threw
|
|
337
|
+
* a bare TypeError rather than a typed refusal. */
|
|
338
|
+
intrinsic.append(items, item);
|
|
332
339
|
}
|
|
333
340
|
var match = { kind: "repeat", node: node, items: items };
|
|
334
341
|
if (schema.build) match.result = schema.build(match, ctx);
|
|
@@ -336,7 +343,7 @@ function _walkRepeat(schema, node, ctx) {
|
|
|
336
343
|
}
|
|
337
344
|
|
|
338
345
|
function _equalsDefault(value, def) {
|
|
339
|
-
if (
|
|
346
|
+
if (intrinsic.isBuffer(value) && intrinsic.isBuffer(def)) return intrinsic.bufferEquals(value, def);
|
|
340
347
|
return value === def;
|
|
341
348
|
}
|
|
342
349
|
|
|
@@ -439,7 +446,7 @@ function _encFail(message) { throw new Error("schema.encode: " + message); }
|
|
|
439
446
|
function encode(schema, value, ctx) {
|
|
440
447
|
switch (schema.kind) {
|
|
441
448
|
case "leaf": return schema.write(value);
|
|
442
|
-
case "any": return
|
|
449
|
+
case "any": return intrinsic.isBuffer(value) ? value : value.bytes;
|
|
443
450
|
case "decode":
|
|
444
451
|
if (typeof schema.write !== "function") _encFail("this decode leaf has no paired encoder (decode(fn, write))");
|
|
445
452
|
return schema.write(value, ctx);
|
|
@@ -453,7 +460,7 @@ function encode(schema, value, ctx) {
|
|
|
453
460
|
}
|
|
454
461
|
|
|
455
462
|
function _wrapConstructed(schema, parts) {
|
|
456
|
-
if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag,
|
|
463
|
+
if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag, intrinsic.bufferConcat(parts));
|
|
457
464
|
var mode = schema.assert || "sequence";
|
|
458
465
|
if (mode === "set") return asn1.build.set(parts);
|
|
459
466
|
if (mode === "sequence" || mode === "constructed") return asn1.build.sequence(parts);
|
|
@@ -469,13 +476,17 @@ function _encodeSeq(schema, value, ctx) {
|
|
|
469
476
|
for (var f = 0; f < schema.fields.length; f++) {
|
|
470
477
|
var fld = schema.fields[f];
|
|
471
478
|
if (fld.fkind === "required") {
|
|
472
|
-
|
|
479
|
+
/** @internal Each field is APPENDED by defining its index, for the reason the repeat walk is:
|
|
480
|
+
* `push` stores, a store consults a setter inherited at the index, and these parts are
|
|
481
|
+
* concatenated in order into the structure this encoder emits. Measured, an accessor at
|
|
482
|
+
* index 0 put its own TLV where the first field belongs. */
|
|
483
|
+
intrinsic.append(parts, encode(fld.schema, value[fld.name], ctx));
|
|
473
484
|
} else if (fld.fkind === "optional") {
|
|
474
485
|
if (_present(value[fld.name])) {
|
|
475
486
|
var enc = encode(fld.schema, value[fld.name], ctx);
|
|
476
487
|
var isDefault = fld.hasDefault && fld.def !== undefined &&
|
|
477
|
-
|
|
478
|
-
if (!isDefault)
|
|
488
|
+
intrinsic.bufferEquals(enc, encode(fld.schema, fld.def, ctx));
|
|
489
|
+
if (!isDefault) intrinsic.append(parts, fld.explicit ? asn1.build.explicit(fld.tag, enc) : enc);
|
|
479
490
|
}
|
|
480
491
|
} else if (fld.fkind === "trailing") {
|
|
481
492
|
var members = guardList.sortedCopy(fld.members, function (a, b) { return a.tag - b.tag; });
|
|
@@ -483,7 +494,7 @@ function _encodeSeq(schema, value, ctx) {
|
|
|
483
494
|
var mm = members[i];
|
|
484
495
|
if (_present(value[mm.name])) {
|
|
485
496
|
var menc = encode(mm.schema, value[mm.name], ctx);
|
|
486
|
-
|
|
497
|
+
intrinsic.append(parts, mm.explicit ? asn1.build.explicit(mm.tag, menc) : menc);
|
|
487
498
|
}
|
|
488
499
|
}
|
|
489
500
|
} else {
|
|
@@ -494,17 +505,21 @@ function _encodeSeq(schema, value, ctx) {
|
|
|
494
505
|
}
|
|
495
506
|
|
|
496
507
|
function _encodeRepeat(schema, items, ctx) {
|
|
497
|
-
if (!
|
|
508
|
+
if (!intrinsic.isArray(items)) _encFail("a repeat value must be an array");
|
|
498
509
|
if (schema.min != null && items.length < schema.min) {
|
|
499
510
|
_encFail("this repeat requires at least " + schema.min + " element(s) but got " + items.length);
|
|
500
511
|
}
|
|
501
512
|
if (schema.max != null && items.length > schema.max) {
|
|
502
513
|
_encFail("this repeat caps at " + schema.max + " element(s) but got " + items.length);
|
|
503
514
|
}
|
|
504
|
-
|
|
515
|
+
/** @internal The elements are mapped through the captured operation, which builds its result by
|
|
516
|
+
* defining each index on a plain array. `Array.prototype.map` is replaceable and reads the
|
|
517
|
+
* receiver's `Symbol.species` to construct what it returns, so a caller's array could both
|
|
518
|
+
* choose the encoded elements and hand this encoder a result object of its own class. */
|
|
519
|
+
var parts = intrinsic.mapList(items, function (it) { return encode(schema.item, it, ctx); });
|
|
505
520
|
if (schema.unique) {
|
|
506
521
|
var seen = new Set();
|
|
507
|
-
|
|
522
|
+
intrinsic.forEach(parts, function (tlv) {
|
|
508
523
|
// allow:bare-decode a round trip through the codec on a TLV this encoder just produced.
|
|
509
524
|
var item = { node: asn1.decode(tlv) };
|
|
510
525
|
item.value = walk(schema.item, item.node, ctx);
|
|
@@ -517,7 +532,7 @@ function _encodeRepeat(schema, items, ctx) {
|
|
|
517
532
|
* is the engine's own SET OF emission, so whatever decides "before" decides the bytes every schema
|
|
518
533
|
* built on it emits. */
|
|
519
534
|
if (schema.derSetOrder) parts = guardList.sortedCopy(parts, intrinsic.compare);
|
|
520
|
-
if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag,
|
|
535
|
+
if (schema.implicitTag != null) return asn1.build.contextConstructed(schema.implicitTag, intrinsic.bufferConcat(parts));
|
|
521
536
|
return schema.assert === "set" ? asn1.build.set(parts) : asn1.build.sequence(parts);
|
|
522
537
|
}
|
|
523
538
|
|
|
@@ -586,11 +601,14 @@ function isUniversal(node, tagNumber) {
|
|
|
586
601
|
function isContext(node, tagNumber) {
|
|
587
602
|
return !!node && node.tagClass === "context" && node.tagNumber === tagNumber;
|
|
588
603
|
}
|
|
604
|
+
/** @internal Both read the OWN elements of the tag list. `indexOf` is specified in terms of
|
|
605
|
+
* HasProperty, so a list with a hole at an index answers from the array prototype, and the list
|
|
606
|
+
* here is an allow-list deciding whether a node's tag is one a schema accepts. */
|
|
589
607
|
function isUniversalOneOf(node, tagNumbers) {
|
|
590
|
-
return !!node && node.tagClass === "universal" &&
|
|
608
|
+
return !!node && node.tagClass === "universal" && intrinsic.ownIndexOf(tagNumbers, node.tagNumber) !== -1;
|
|
591
609
|
}
|
|
592
610
|
function isContextOneOf(node, tagNumbers) {
|
|
593
|
-
return !!node && node.tagClass === "context" &&
|
|
611
|
+
return !!node && node.tagClass === "context" && intrinsic.ownIndexOf(tagNumbers, node.tagNumber) !== -1;
|
|
594
612
|
}
|
|
595
613
|
function isContextInRange(node, min, max) {
|
|
596
614
|
return !!node && node.tagClass === "context" && node.tagNumber >= min && node.tagNumber <= max;
|
package/lib/schema-pkcs1.js
CHANGED
|
@@ -264,11 +264,15 @@ function encode(key) {
|
|
|
264
264
|
var infos = key.otherPrimeInfos;
|
|
265
265
|
if (intrinsic.isArray(infos) && infos.length > 0) {
|
|
266
266
|
var rows = [];
|
|
267
|
+
/** @internal Both appends define the index. A store at an index a list has no own property at
|
|
268
|
+
* walks the prototype chain for a setter, so an accessor there took the element and the list
|
|
269
|
+
* read back whatever its getter answers; `kids` holds nine own slots here, so index nine is
|
|
270
|
+
* such a store. These are the bytes a private key encodes to. */
|
|
267
271
|
for (var i = 0; i < infos.length; i++) {
|
|
268
|
-
rows
|
|
269
|
-
asn1.build.integer(infos[i].exponent), asn1.build.integer(infos[i].coefficient)]);
|
|
272
|
+
intrinsic.append(rows, asn1.build.sequence([asn1.build.integer(infos[i].prime),
|
|
273
|
+
asn1.build.integer(infos[i].exponent), asn1.build.integer(infos[i].coefficient)]));
|
|
270
274
|
}
|
|
271
|
-
kids
|
|
275
|
+
intrinsic.append(kids, asn1.build.sequence(rows));
|
|
272
276
|
}
|
|
273
277
|
return asn1.build.sequence(kids);
|
|
274
278
|
}
|
package/lib/schema-pkcs12.js
CHANGED
|
@@ -47,6 +47,9 @@ var cms = require("./schema-cms.js");
|
|
|
47
47
|
var pkcs8 = require("./schema-pkcs8.js");
|
|
48
48
|
var frameworkError = require("./framework-error.js");
|
|
49
49
|
var guard = require("./guard-all.js");
|
|
50
|
+
/** @internal The append this module's lists are built with: `push` stores at the index and a store
|
|
51
|
+
* consults a setter inherited there, which takes the element being appended. */
|
|
52
|
+
var _push = guard.list.append;
|
|
50
53
|
|
|
51
54
|
var Pkcs12Error = frameworkError.Pkcs12Error;
|
|
52
55
|
var PemError = frameworkError.PemError;
|
|
@@ -181,7 +184,7 @@ var SAFE_BAG = schema.seq([
|
|
|
181
184
|
var items = m.fields.bagAttributes.value.items;
|
|
182
185
|
for (var i = 0; i < items.length; i++) {
|
|
183
186
|
var a = items[i].value.result;
|
|
184
|
-
attributes
|
|
187
|
+
_push(attributes, a);
|
|
185
188
|
if (a.type === OID_FRIENDLY_NAME) {
|
|
186
189
|
if (seen[a.type] || a.values.length !== 1) throw ctx.E("pkcs12/bad-friendly-name", "friendlyName carries exactly one BMPString value (PKCS#9 SINGLE VALUE)");
|
|
187
190
|
friendlyName = _bmpValue(a.values[0], ctx);
|
|
@@ -319,7 +322,7 @@ function walkSafeContents(der, ctx) {
|
|
|
319
322
|
var walked = schema.walk(SAFE_CONTENTS, pkix.decodeNested(der, ns, "a SafeContents", { ber: true }), ns);
|
|
320
323
|
var state = { budget: { remaining: C.LIMITS.PKCS12_MAX_REDECODES }, bagDepth: 0 };
|
|
321
324
|
var bags = [];
|
|
322
|
-
for (var i = 0; i < walked.items.length; i++) bags
|
|
325
|
+
for (var i = 0; i < walked.items.length; i++) _push(bags, _buildBag(walked.items[i].value.result, state, ns));
|
|
323
326
|
return bags;
|
|
324
327
|
}
|
|
325
328
|
|
|
@@ -334,12 +337,12 @@ function _dispatchSafes(asMatch, state, ctx) {
|
|
|
334
337
|
budget: state.budget, budgetCode: "pkcs12/too-deep",
|
|
335
338
|
});
|
|
336
339
|
for (var j = 0; j < contents.items.length; j++) {
|
|
337
|
-
safeBags
|
|
340
|
+
_push(safeBags, _buildBag(contents.items[j].value.result, state, ctx));
|
|
338
341
|
}
|
|
339
342
|
} else if (el.contentType === OID_ENCRYPTED_DATA) {
|
|
340
|
-
encryptedSafes
|
|
343
|
+
_push(encryptedSafes, { type: "encryptedData", content: _privacySafe(cms.walkEncryptedData(el.innerNode, ctx), ctx) });
|
|
341
344
|
} else if (el.contentType === OID_ENVELOPED_DATA) {
|
|
342
|
-
encryptedSafes
|
|
345
|
+
_push(encryptedSafes, { type: "envelopedData", content: _privacySafe(cms.walkEnvelopedData(el.innerNode, ctx), ctx), envelopedDataDer: el.innerNode.bytes });
|
|
343
346
|
} else {
|
|
344
347
|
throw ctx.E("pkcs12/bad-safe-contentinfo-type", "an AuthenticatedSafe element must be id-data, id-encryptedData, or id-envelopedData (RFC 7292 sec. 4.1), got " +
|
|
345
348
|
(ctx.oid.name(el.contentType) || el.contentType));
|
|
@@ -391,7 +394,7 @@ function _buildBag(rec, state, ctx) {
|
|
|
391
394
|
bag.nested = [];
|
|
392
395
|
var nestedMatch = schema.walk(SAFE_CONTENTS, rec.valueNode, ctx);
|
|
393
396
|
for (var i = 0; i < nestedMatch.items.length; i++) {
|
|
394
|
-
bag.nested
|
|
397
|
+
_push(bag.nested, _buildBag(nestedMatch.items[i].value.result, nestedState, ctx));
|
|
395
398
|
}
|
|
396
399
|
return bag;
|
|
397
400
|
}
|
package/lib/schema-pkix.js
CHANGED
|
@@ -11,8 +11,17 @@ var intrinsic = require("./guard-intrinsic");
|
|
|
11
11
|
var frameworkError = require("./framework-error");
|
|
12
12
|
var _hasOwn = intrinsic.hasOwn;
|
|
13
13
|
var _forEach = intrinsic.forEach;
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
/** @internal `mapList`, not the captured `map`. `Array.prototype.map` is specified to build its
|
|
15
|
+
* result through `ArraySpeciesCreate`, which reads the receiver's `constructor` and then that
|
|
16
|
+
* constructor's `Symbol.species`, so a getter installed on `Array.prototype.constructor` runs
|
|
17
|
+
* caller code with the list being mapped as its `this` on every call. Capturing the method closes
|
|
18
|
+
* which function runs, not the protocol it consults. Measured on a certificate parse: the
|
|
19
|
+
* extension-list build was reached that way. `mapList` defines each index on a plain array. */
|
|
20
|
+
var _map = intrinsic.mapList;
|
|
21
|
+
/** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
|
|
22
|
+
* setter, so an accessor there takes the element being appended. The lists built here are the parsed
|
|
23
|
+
* members every format module reads its fields from. `append` defines the index. */
|
|
24
|
+
var _push = intrinsic.append;
|
|
16
25
|
var _join = intrinsic.join;
|
|
17
26
|
var _stringify = intrinsic.stringify;
|
|
18
27
|
var _String = intrinsic.String;
|
|
@@ -51,7 +60,14 @@ function _hasNonWhitespace(s) {
|
|
|
51
60
|
for (var i = 0; i < s.length; i++) { if (!_isJsWhitespace(_charCodeAt(s, i))) return true; }
|
|
52
61
|
return false;
|
|
53
62
|
}
|
|
54
|
-
|
|
63
|
+
/** @internal The table has NO PROTOTYPE, because it is deliberately sparse: it holds an entry for
|
|
64
|
+
* each character it allows and nothing at the codes it does not, and `_allCharsIn` below reads it at
|
|
65
|
+
* the code of each character it is asked about. Built as an array literal, every code outside the
|
|
66
|
+
* allowed set was a hole, so a value installed at that index on `Array.prototype` answered the
|
|
67
|
+
* check: measured, `Array.prototype[47] = true` made `pki.acme.keyAuthorization` accept a challenge
|
|
68
|
+
* token containing `/`, which the base64url set does not allow, instead of refusing it with
|
|
69
|
+
* `acme/bad-token`. The same helper in lib/guard-name.js has always been written this way. */
|
|
70
|
+
function _charTable(chars) { var t = _create(null); for (var i = 0; i < chars.length; i++) t[_charCodeAt(chars, i)] = true; return t; }
|
|
55
71
|
function _allCharsIn(s, table) {
|
|
56
72
|
if (s.length === 0) return false;
|
|
57
73
|
for (var i = 0; i < s.length; i++) { if (!table[_charCodeAt(s, i)]) return false; }
|
package/lib/schema-sec1.js
CHANGED
|
@@ -210,7 +210,10 @@ function encode(key) {
|
|
|
210
210
|
asn1.build.octetString(key.privateKey),
|
|
211
211
|
asn1.build.explicit(0, asn1.build.oid(curveOid))];
|
|
212
212
|
if (key.publicKey !== undefined && key.publicKey !== null) {
|
|
213
|
-
|
|
213
|
+
/** @internal Appended by defining the index. `kids` holds three own slots above, so assigning at
|
|
214
|
+
* index three is a store, and a store walks the prototype chain for a setter: an accessor there
|
|
215
|
+
* would take the public key out of the structure this encodes. */
|
|
216
|
+
intrinsic.append(kids, asn1.build.explicit(1, asn1.build.bitString(key.publicKey, 0)));
|
|
214
217
|
}
|
|
215
218
|
return asn1.build.sequence(kids);
|
|
216
219
|
}
|
package/lib/schema-tsp.js
CHANGED
|
@@ -43,6 +43,9 @@ var smime = require("./schema-smime");
|
|
|
43
43
|
var cms = require("./schema-cms");
|
|
44
44
|
var frameworkError = require("./framework-error");
|
|
45
45
|
var guard = require("./guard-all");
|
|
46
|
+
/** @internal The append this module's lists are built with: `push` stores at the index and a store
|
|
47
|
+
* consults a setter inherited there, which takes the element being appended. */
|
|
48
|
+
var _push = guard.list.append;
|
|
46
49
|
|
|
47
50
|
var TspError = frameworkError.TspError;
|
|
48
51
|
var PemError = frameworkError.PemError;
|
|
@@ -196,7 +199,7 @@ function _namedBits(bytes) {
|
|
|
196
199
|
if ((bytes[i >> 3] >> (7 - (i & 7))) & 1) {
|
|
197
200
|
var nm = FAILURE_BITS[i];
|
|
198
201
|
if (!nm) throw NS.E("tsp/bad-failinfo", "unsupported PKIFailureInfo bit " + i + " (RFC 3161 sec. 2.4.2)");
|
|
199
|
-
out
|
|
202
|
+
_push(out, nm);
|
|
200
203
|
}
|
|
201
204
|
}
|
|
202
205
|
return out;
|
|
@@ -525,8 +528,8 @@ function essDigest(name) {
|
|
|
525
528
|
var xof = ESS_XOF_BYTES[name];
|
|
526
529
|
/** @internal One read of the name answers both whether the digest can be computed and how to
|
|
527
530
|
* compute it, so the hash every candidate is put through is the one that read settled. */
|
|
528
|
-
return function () {
|
|
529
|
-
return xof ?
|
|
531
|
+
return function (bytes) {
|
|
532
|
+
return xof ? guard.crypto.xof(name, bytes, xof) : guard.crypto.digest(name, bytes);
|
|
530
533
|
};
|
|
531
534
|
}
|
|
532
535
|
|
|
@@ -576,7 +579,7 @@ function _essNamedCertificate(token, attr) {
|
|
|
576
579
|
for (var j = 0; j < certs.length; j++) {
|
|
577
580
|
var element = certs[j];
|
|
578
581
|
if (!element || element.tagClass !== "universal" || !Buffer.isBuffer(element.bytes)) continue;
|
|
579
|
-
var actual = digest(
|
|
582
|
+
var actual = digest(element.bytes);
|
|
580
583
|
if (actual.length === want.length && guard.bytes.compare(actual, want) === 0) return element.bytes;
|
|
581
584
|
}
|
|
582
585
|
return null;
|
package/lib/shbs.js
CHANGED
|
@@ -21,9 +21,12 @@
|
|
|
21
21
|
* @card Verify HSS/LMS signatures (post-quantum, CNSA 2.0 firmware signing).
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
var nodeCrypto = require("crypto");
|
|
25
24
|
var frameworkError = require("./framework-error");
|
|
26
25
|
var guard = require("./guard-all");
|
|
26
|
+
/** @internal The append every list here is built with: `push` stores at the index and a store
|
|
27
|
+
* consults a setter inherited there, and these lists are the authentication path and the one-time
|
|
28
|
+
* values a hash-based signature is formed from. */
|
|
29
|
+
var _push = guard.list.append;
|
|
27
30
|
var constants = require("./constants");
|
|
28
31
|
|
|
29
32
|
var ShbsError = frameworkError.ShbsError;
|
|
@@ -78,11 +81,9 @@ function _lmotsSet(code) {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
function _hash(family, n, parts) {
|
|
81
|
-
var
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
for (var i = 0; i < parts.length; i++) h.update(parts[i]);
|
|
85
|
-
var d = h.digest();
|
|
84
|
+
var d = family === "shake256"
|
|
85
|
+
? guard.crypto.digestParts("shake256", parts, n)
|
|
86
|
+
: guard.crypto.digestParts("sha256", parts);
|
|
86
87
|
return (family === "shake256" || n === 32) ? d : d.subarray(0, n);
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -124,7 +125,7 @@ function _lmotsKc(otsSet, I, q, C, y, message) {
|
|
|
124
125
|
var a = _coef(Qc, i, w);
|
|
125
126
|
var tmp = y[i];
|
|
126
127
|
for (var j = a; j < (1 << w) - 1; j++) tmp = _hash(f, n, [I, qb, u16(i), u8(j), tmp]);
|
|
127
|
-
z
|
|
128
|
+
_push(z,tmp);
|
|
128
129
|
}
|
|
129
130
|
return _hash(f, n, z);
|
|
130
131
|
}
|
|
@@ -148,11 +149,11 @@ function _lmsVerify(pubBytes, message, sigBytes) {
|
|
|
148
149
|
var n = otsSet.n, p = otsSet.p;
|
|
149
150
|
var C = sr.take(n);
|
|
150
151
|
var y = [];
|
|
151
|
-
for (var yi = 0; yi < p; yi++) y
|
|
152
|
+
for (var yi = 0; yi < p; yi++) _push(y,sr.take(n));
|
|
152
153
|
var sigLmsType = sr.u32();
|
|
153
154
|
if (sigLmsType !== lmsSet.code) return false;
|
|
154
155
|
var path = [];
|
|
155
|
-
for (var pi = 0; pi < h; pi++) path
|
|
156
|
+
for (var pi = 0; pi < h; pi++) _push(path,sr.take(m));
|
|
156
157
|
if (!sr.atEnd()) throw _err("shbs/bad-signature", "LMS signature has " + sr.remaining() + " trailing byte(s)");
|
|
157
158
|
if (q >= Math.pow(2, h)) return false;
|
|
158
159
|
|
package/lib/sign-scheme.js
CHANGED
|
@@ -359,14 +359,14 @@ function _keyTypeAccepts(reported, wanted) {
|
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
function _assertKeyObjectMatchesScheme(key, scheme, E) {
|
|
362
|
-
var reported = key
|
|
362
|
+
var reported = guard.crypto.keyType(key);
|
|
363
363
|
var wanted = NODE_KEY_TYPE[scheme.imp.name] || _toLowerCase(_String(scheme.imp.name));
|
|
364
364
|
if (!_keyTypeAccepts(reported, wanted)) {
|
|
365
365
|
throw E("bad-input", "the signer KeyObject algorithm (" + reported +
|
|
366
366
|
") does not match the certificate's key algorithm (" + scheme.imp.name + ")");
|
|
367
367
|
}
|
|
368
368
|
if (scheme.imp.namedCurve) {
|
|
369
|
-
var details = key
|
|
369
|
+
var details = guard.crypto.keyDetails(key);
|
|
370
370
|
var curve = details && details.namedCurve;
|
|
371
371
|
if (curve !== NODE_CURVE[scheme.imp.namedCurve]) {
|
|
372
372
|
throw E("bad-input", "the signer KeyObject curve (" + curve +
|
package/lib/sigstore.js
CHANGED
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
* @card Verify an npm --provenance Sigstore bundle offline (DSSE + Fulcio + Rekor + SLSA).
|
|
29
29
|
*/
|
|
30
30
|
|
|
31
|
-
var nodeCrypto = require("crypto");
|
|
32
31
|
var frameworkError = require("./framework-error");
|
|
33
32
|
var constants = require("./constants");
|
|
34
33
|
var asn1 = require("./asn1-der");
|
|
@@ -227,8 +226,8 @@ function _assertKeyDetailsParameters(want, leafSpki, declared) {
|
|
|
227
226
|
if (want.bits !== undefined) {
|
|
228
227
|
var bits;
|
|
229
228
|
try {
|
|
230
|
-
bits = guard.crypto.
|
|
231
|
-
.
|
|
229
|
+
bits = guard.crypto.keyDetails(
|
|
230
|
+
guard.crypto.publicKey({ key: leafSpki.bytes, format: "der", type: "spki" })).modulusLength;
|
|
232
231
|
} catch (_e) { bits = null; } // allow:swallow-unverified -- a key that will not import has no modulus size to match, and the mismatch below is the verdict
|
|
233
232
|
if (bits !== want.bits) {
|
|
234
233
|
throw _err("sigstore/entry-mismatch", "the Rekor entry states the signing key is " +
|
|
@@ -709,13 +708,14 @@ function _chainDers(vm) {
|
|
|
709
708
|
}
|
|
710
709
|
|
|
711
710
|
function _rawVerify(keyObj, data, derSig) {
|
|
712
|
-
var t = keyObj
|
|
711
|
+
var t = guard.crypto.keyType(keyObj);
|
|
713
712
|
if (t === "ed25519" || t === "ed448") {
|
|
714
713
|
var edSpki = guard.crypto.exportKey(keyObj, { type: "spki", format: "der" });
|
|
715
714
|
edwardsPoint.validateSpki(edSpki, t === "ed25519" ? 6 : 7, SigstoreError, "sigstore/bad-key");
|
|
716
715
|
return guard.crypto.verify(null, data, keyObj, derSig);
|
|
717
716
|
}
|
|
718
|
-
var
|
|
717
|
+
var keyObjDetails = guard.crypto.keyDetails(keyObj);
|
|
718
|
+
var crv = keyObjDetails && keyObjDetails.namedCurve;
|
|
719
719
|
var hash = crv === "secp384r1" ? "sha384" : (crv === "secp521r1" ? "sha512" : "sha256");
|
|
720
720
|
return guard.crypto.verify(hash, data, { key: keyObj, dsaEncoding: "der" }, derSig);
|
|
721
721
|
}
|
|
@@ -723,7 +723,7 @@ function _pubFromSpki(spkiDer, label) {
|
|
|
723
723
|
var key;
|
|
724
724
|
try { key = guard.crypto.publicKey({ key: spkiDer, format: "der", type: "spki" }); }
|
|
725
725
|
catch (e) { throw _err("sigstore/bad-key", "invalid " + label + " public key", e); }
|
|
726
|
-
var t = key
|
|
726
|
+
var t = guard.crypto.keyType(key);
|
|
727
727
|
if (t === "ed25519" || t === "ed448") {
|
|
728
728
|
edwardsPoint.validateSpki(spkiDer, t === "ed25519" ? 6 : 7, SigstoreError, "sigstore/bad-key");
|
|
729
729
|
}
|
|
@@ -735,7 +735,7 @@ function _parseCert(der, label) {
|
|
|
735
735
|
}
|
|
736
736
|
|
|
737
737
|
|
|
738
|
-
function _sha256(buf) { return
|
|
738
|
+
function _sha256(buf) { return guard.crypto.digest("sha256", buf); }
|
|
739
739
|
|
|
740
740
|
function _toMs(x) {
|
|
741
741
|
if (x == null) return null;
|
|
@@ -1109,7 +1109,7 @@ function _bindHashedRekordV002Entry(body, arm, leafDer, contentType, payloadType
|
|
|
1109
1109
|
}
|
|
1110
1110
|
var digest = _b64(data.digest, "hashedRekordV002.data.digest");
|
|
1111
1111
|
if (contentType === "dsseEnvelope") {
|
|
1112
|
-
var computed =
|
|
1112
|
+
var computed = guard.crypto.digest(alg.node, pae(payloadType, payload));
|
|
1113
1113
|
if (!guard.crypto.constantTimeEqual(computed, digest)) {
|
|
1114
1114
|
throw _err("sigstore/entry-mismatch", "the Rekor entry digest is not the hash of this envelope's " +
|
|
1115
1115
|
"signing preimage, so the entry records a different signature than the bundle carries");
|
|
@@ -1831,7 +1831,7 @@ async function verifyBundle(bundle, opts) {
|
|
|
1831
1831
|
var artifactDigests = intrinsic.create(null);
|
|
1832
1832
|
function _artifactDigest(nodeName) {
|
|
1833
1833
|
if (!intrinsic.hasOwn(artifactDigests, nodeName)) {
|
|
1834
|
-
artifactDigests[nodeName] =
|
|
1834
|
+
artifactDigests[nodeName] = guard.crypto.digest(nodeName, artifact);
|
|
1835
1835
|
}
|
|
1836
1836
|
return artifactDigests[nodeName];
|
|
1837
1837
|
}
|
package/lib/smime.js
CHANGED
|
@@ -41,10 +41,13 @@ var schemaX509 = require("./schema-x509.js");
|
|
|
41
41
|
var pkix = require("./schema-pkix.js");
|
|
42
42
|
var oid = require("./oid.js");
|
|
43
43
|
var guard = require("./guard-all.js");
|
|
44
|
+
/** @internal The append every list here is built with: `push` stores at the index and a store
|
|
45
|
+
* consults a setter inherited there, and these lists become the headers and parts a signed or
|
|
46
|
+
* encrypted message carries. */
|
|
47
|
+
var _push = guard.list.append;
|
|
44
48
|
var pkiBuild = require("./pki-build.js");
|
|
45
49
|
var C = require("./constants.js");
|
|
46
50
|
var nodeUtil = require("util");
|
|
47
|
-
var nodeCrypto = require("crypto");
|
|
48
51
|
|
|
49
52
|
var SmimeError = frameworkError.SmimeError;
|
|
50
53
|
|
|
@@ -118,13 +121,13 @@ function _hpHeaderList(headers) {
|
|
|
118
121
|
if (!h || typeof h !== "object") throw _err("smime/bad-input", "each opts.headers entry must be { name, value }");
|
|
119
122
|
var name = h.name, v = h.value;
|
|
120
123
|
if (typeof name !== "string") throw _err("smime/bad-input", "each opts.headers entry must be { name, value }");
|
|
121
|
-
out
|
|
124
|
+
_push(out,{ name: name, value: v == null ? "" : String(v) });
|
|
122
125
|
});
|
|
123
126
|
} else if (typeof headers === "object") {
|
|
124
127
|
var hn = guard.identifier.optionNames(headers);
|
|
125
128
|
for (var hi = 0; hi < hn.length; hi++) {
|
|
126
129
|
var hv = headers[hn[hi]];
|
|
127
|
-
out
|
|
130
|
+
_push(out,{ name: hn[hi], value: hv == null ? "" : String(hv) });
|
|
128
131
|
}
|
|
129
132
|
} else {
|
|
130
133
|
throw _err("smime/bad-input", "opts.headers must be an object or an array of { name, value }");
|
|
@@ -155,9 +158,9 @@ function _outerHeaderList(list, mode, hcp) {
|
|
|
155
158
|
list.forEach(function (h) {
|
|
156
159
|
if (mode === "cipher") {
|
|
157
160
|
var v = _applyHcp(h.name, h.value, policy);
|
|
158
|
-
if (v !== null) out
|
|
161
|
+
if (v !== null) _push(out,{ name: h.name, value: v });
|
|
159
162
|
} else {
|
|
160
|
-
out
|
|
163
|
+
_push(out,{ name: h.name, value: h.value });
|
|
161
164
|
}
|
|
162
165
|
});
|
|
163
166
|
return out;
|
|
@@ -171,9 +174,9 @@ function _protectedInnerEntity(content, opts, mode, hpList, outerList) {
|
|
|
171
174
|
if (cty != null && mime.hasParam(cty, "hp")) throw _err("smime/bad-input", "opts.contentType must not set the hp parameter -- header protection sets it (hp=" + guard.text.showValue(mode) + ")");
|
|
172
175
|
var ct = (cty || "text/plain; charset=utf-8") + "; hp=\"" + mode + "\"";
|
|
173
176
|
var fields = [{ name: "Content-Type", value: ct }, { name: "Content-Transfer-Encoding", value: _is7bit(raw) ? "7bit" : "8bit" }];
|
|
174
|
-
hpList.forEach(function (h) { fields
|
|
177
|
+
hpList.forEach(function (h) { _push(fields,h); });
|
|
175
178
|
if (mode === "cipher") {
|
|
176
|
-
outerList.forEach(function (h) { fields
|
|
179
|
+
outerList.forEach(function (h) { _push(fields,{ name: "HP-Outer", value: h.name + ": " + h.value }); });
|
|
177
180
|
}
|
|
178
181
|
return mime.buildEntity(fields, raw, SmimeError, "smime/bad-header");
|
|
179
182
|
}
|
|
@@ -227,7 +230,7 @@ function _contentTypeLines(s) {
|
|
|
227
230
|
var lines = [], lineStart = 0;
|
|
228
231
|
while (lineStart <= s.length) {
|
|
229
232
|
var line = _contentTypeLineAt(s, lineStart);
|
|
230
|
-
if (line !== null) lines
|
|
233
|
+
if (line !== null) _push(lines,line);
|
|
231
234
|
var nl = s.indexOf("\n", lineStart);
|
|
232
235
|
if (nl === -1) break;
|
|
233
236
|
lineStart = nl + 1;
|
|
@@ -274,11 +277,11 @@ function _extractProtected(headerList) {
|
|
|
274
277
|
if (_isStructural(h.lname)) return;
|
|
275
278
|
if (h.lname === "hp-outer") {
|
|
276
279
|
var ci = h.rawValue.indexOf(":");
|
|
277
|
-
if (ci >= 0) refouter
|
|
280
|
+
if (ci >= 0) _push(refouter,{ name: h.rawValue.slice(0, ci).trim().toLowerCase(), value: h.rawValue.slice(ci + 1).trim() });
|
|
278
281
|
return;
|
|
279
282
|
}
|
|
280
283
|
var val = _utf8Header(h.rawValue);
|
|
281
|
-
entries
|
|
284
|
+
_push(entries,{ name: h.name, value: val, raw: h.rawValue });
|
|
282
285
|
if (seen[h.lname]) { dup = h.name; if (RFC5322_SINGLETON.has(h.lname)) dupSingleton = h.name; }
|
|
283
286
|
seen[h.lname] = 1;
|
|
284
287
|
protectedHeaders[h.name] = val;
|
|
@@ -297,7 +300,7 @@ function _computeConfidential(entries, refouter) {
|
|
|
297
300
|
entries.forEach(function (e) {
|
|
298
301
|
var m = byName.get(e.name.toLowerCase()), val = e.raw.trim(), n = (m && m.get(val)) || 0;
|
|
299
302
|
if (n > 0) { m.set(val, n - 1); return; }
|
|
300
|
-
if (!seen[e.name]) { seen[e.name] = 1; confidential
|
|
303
|
+
if (!seen[e.name]) { seen[e.name] = 1; _push(confidential,e.name); }
|
|
301
304
|
});
|
|
302
305
|
return confidential;
|
|
303
306
|
}
|
|
@@ -305,7 +308,7 @@ function _computeConfidential(entries, refouter) {
|
|
|
305
308
|
function _computeFromMismatch(innerFrom, outerEnt) {
|
|
306
309
|
if (innerFrom == null) return null;
|
|
307
310
|
var outerFroms = [];
|
|
308
|
-
outerEnt.headers.forEach(function (h) { if (h.lname === "from") outerFroms
|
|
311
|
+
outerEnt.headers.forEach(function (h) { if (h.lname === "from") _push(outerFroms,h.value.trim()); });
|
|
309
312
|
return outerFroms.length !== 1 || outerFroms[0] !== innerFrom.trim();
|
|
310
313
|
}
|
|
311
314
|
|
|
@@ -315,7 +318,7 @@ function _isCryptoLayer(type) {
|
|
|
315
318
|
|
|
316
319
|
function _outerRefouter(outerEnt) {
|
|
317
320
|
var r = [];
|
|
318
|
-
outerEnt.headers.forEach(function (h) { if (!_isStructural(h.lname) && h.lname !== "hp-outer") r
|
|
321
|
+
outerEnt.headers.forEach(function (h) { if (!_isStructural(h.lname) && h.lname !== "hp-outer") _push(r,{ name: h.lname, value: h.rawValue.trim() }); });
|
|
319
322
|
return r;
|
|
320
323
|
}
|
|
321
324
|
|
|
@@ -572,7 +575,7 @@ function _cmsSignOpts(opts, detached) {
|
|
|
572
575
|
function _micName(name) { return name ? (MICALG[name] || name) : null; }
|
|
573
576
|
function _micalgSet(value) {
|
|
574
577
|
var seen = [];
|
|
575
|
-
String(value).split(",").forEach(function (m) { var t = m.trim().toLowerCase(); if (t && seen.indexOf(t) < 0) seen
|
|
578
|
+
String(value).split(",").forEach(function (m) { var t = m.trim().toLowerCase(); if (t && seen.indexOf(t) < 0) _push(seen,t); });
|
|
576
579
|
return seen.sort().join(",");
|
|
577
580
|
}
|
|
578
581
|
function _micalgOf(p7Der) {
|
|
@@ -582,12 +585,12 @@ function _micalgOf(p7Der) {
|
|
|
582
585
|
var out = [];
|
|
583
586
|
(parsed.signerInfos || []).forEach(function (si) {
|
|
584
587
|
var mic = _micName(si.digestAlgorithm && si.digestAlgorithm.name);
|
|
585
|
-
if (mic && out.indexOf(mic) < 0) out
|
|
588
|
+
if (mic && out.indexOf(mic) < 0) _push(out,mic);
|
|
586
589
|
});
|
|
587
590
|
return out.length ? out.sort().join(",") : null;
|
|
588
591
|
}
|
|
589
592
|
|
|
590
|
-
function _boundary() { return "----=_pki_smime_" +
|
|
593
|
+
function _boundary() { return "----=_pki_smime_" + guard.crypto.randomBytes(18).toString("hex"); }
|
|
591
594
|
|
|
592
595
|
function _wrap64Crlf(s) {
|
|
593
596
|
var out = "";
|
package/lib/tlog.js
CHANGED
|
@@ -69,9 +69,10 @@ var _strSlice = intrinsic.uncurry(String.prototype.slice);
|
|
|
69
69
|
var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
|
|
70
70
|
var _arrSlice = intrinsic.arraySlice;
|
|
71
71
|
var _join = intrinsic.join;
|
|
72
|
-
|
|
72
|
+
/** @internal `append`, not a captured `push`: a store at an index walks the prototype chain for a
|
|
73
|
+
* setter, so an accessor there takes the element being appended. `append` defines it. */
|
|
74
|
+
var _push = intrinsic.append;
|
|
73
75
|
var _pop = intrinsic.pop;
|
|
74
|
-
var _unshift = intrinsic.unshift;
|
|
75
76
|
var _bufToString = intrinsic.bufToString;
|
|
76
77
|
var _bufferFrom = intrinsic.bufferFrom;
|
|
77
78
|
var _byteLength = intrinsic.byteLength;
|
|
@@ -298,12 +299,13 @@ function _resolveKey(keyName, publicKey) {
|
|
|
298
299
|
throw _err("tlog/bad-input", "publicKey must be the raw " + ED25519_RAW_BYTES +
|
|
299
300
|
" Ed25519 bytes or a SubjectPublicKeyInfo, got " + bytes.length + " bytes", e);
|
|
300
301
|
}
|
|
301
|
-
var type = key
|
|
302
|
+
var type = guard.crypto.keyType(key);
|
|
302
303
|
if (type === "ed25519") {
|
|
303
304
|
return _edKey(name, bytes, _subarray(bytes, bytes.length - ED25519_RAW_BYTES));
|
|
304
305
|
}
|
|
305
306
|
if (type === "ec") {
|
|
306
|
-
var
|
|
307
|
+
var keyDetails = guard.crypto.keyDetails(key);
|
|
308
|
+
var curve = keyDetails && keyDetails.namedCurve;
|
|
307
309
|
if (EC_CURVES[curve] !== 1) {
|
|
308
310
|
throw _err("tlog/bad-input", "a signed note names no key-ID derivation for the elliptic curve " +
|
|
309
311
|
guard.text.showValue(_stringOf(curve)));
|
|
@@ -798,20 +800,25 @@ var MAX_INDEX_SEGMENTS = (function () {
|
|
|
798
800
|
return count;
|
|
799
801
|
})();
|
|
800
802
|
|
|
803
|
+
/** @internal The segments are counted and then APPENDED most-significant first, by defining each
|
|
804
|
+
* index. Prepending STORES at an index, and a store walks the prototype chain for a setter, so an
|
|
805
|
+
* accessor inherited at an array index took each segment and left the list reading back its getter's
|
|
806
|
+
* value; the `x` prefix was then applied by a read-modify-write through the same hole. These
|
|
807
|
+
* segments are the path a tile is requested from, so the list decides which bytes a verification
|
|
808
|
+
* reads. */
|
|
801
809
|
function _indexPath(index) {
|
|
802
810
|
var n = guard.range.uint64(index, _err, "tlog/bad-tile", "a tile index");
|
|
803
|
-
var segments = [];
|
|
804
|
-
var rest = n;
|
|
805
811
|
var thousand = 1000n;
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
812
|
+
var count = 1;
|
|
813
|
+
for (var probe = n / thousand; probe > 0n; probe = probe / thousand) count++;
|
|
814
|
+
var segments = [];
|
|
815
|
+
for (var k = count - 1; k >= 0; k--) {
|
|
816
|
+
var scale = 1n;
|
|
817
|
+
for (var p = 0; p < k; p++) scale = scale * thousand;
|
|
818
|
+
var text = _stringOf((n / scale) % thousand);
|
|
809
819
|
while (text.length < TILE_SEGMENT_DIGITS) text = "0" + text;
|
|
810
|
-
|
|
811
|
-
rest = rest / thousand;
|
|
812
|
-
if (rest === 0n) break;
|
|
820
|
+
_push(segments, k === 0 ? text : "x" + text);
|
|
813
821
|
}
|
|
814
|
-
for (var i = 0; i < segments.length - 1; i++) segments[i] = "x" + segments[i];
|
|
815
822
|
return _join(segments, "/");
|
|
816
823
|
}
|
|
817
824
|
|