@blamejs/pki 0.8.58 → 0.8.60
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 +50 -0
- package/lib/acme.js +53 -30
- package/lib/alt-sig.js +3 -1
- package/lib/asn1-der.js +98 -39
- 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 +16 -10
- package/lib/cmp-build.js +45 -34
- package/lib/cmp-session.js +19 -9
- package/lib/cms-decrypt.js +28 -10
- package/lib/cms-encrypt.js +23 -17
- package/lib/cms-sign.js +65 -43
- package/lib/cms-verify.js +11 -7
- package/lib/crl-sign.js +27 -20
- package/lib/csr-sign.js +5 -2
- package/lib/ct.js +37 -17
- package/lib/est.js +55 -32
- package/lib/guard-bytes.js +5 -1
- package/lib/guard-der.js +6 -1
- package/lib/guard-identifier.js +1 -1
- package/lib/guard-intrinsic.js +12 -4
- package/lib/guard-list.js +64 -0
- package/lib/guard-name.js +1 -1
- package/lib/hpke.js +10 -3
- package/lib/http-transport.js +12 -3
- package/lib/inspect.js +10 -2
- package/lib/jose.js +3 -1
- package/lib/key.js +11 -7
- package/lib/lint.js +236 -152
- package/lib/mime.js +9 -5
- package/lib/ocsp.js +25 -22
- package/lib/path-validate.js +48 -18
- package/lib/pbes2.js +6 -2
- package/lib/pkcs11-uri.js +3 -1
- package/lib/pkcs12-build.js +14 -11
- package/lib/pki-build.js +18 -14
- package/lib/possession.js +3 -1
- package/lib/rc2.js +6 -2
- package/lib/revocation-fetch.js +78 -19
- package/lib/scep.js +14 -6
- 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 +4 -1
- package/lib/shbs.js +7 -3
- package/lib/sign-scheme.js +4 -4
- package/lib/smime.js +18 -14
- package/lib/tlog.js +17 -11
- package/lib/tuf.js +3 -1
- package/lib/validator-keydesc.js +4 -1
- package/lib/validator-tls.js +7 -2
- package/lib/webcrypto.js +14 -8
- package/lib/x509-sign.js +20 -15
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/crl-sign.js
CHANGED
|
@@ -24,6 +24,9 @@ var x509Schema = require("./schema-x509");
|
|
|
24
24
|
var signScheme = require("./sign-scheme");
|
|
25
25
|
var guard = require("./guard-all");
|
|
26
26
|
var intrinsic = require("./guard-intrinsic");
|
|
27
|
+
/** @internal The append every list here is built with: `push` stores at the index and a store
|
|
28
|
+
* consults a setter inherited there, and these lists become the bytes that get signed. */
|
|
29
|
+
var _push = intrinsic.append;
|
|
27
30
|
var _hasOwn = intrinsic.hasOwn, _bufferEquals = intrinsic.bufferEquals;
|
|
28
31
|
var _arrSlice = intrinsic.arraySlice, _promiseResolve = intrinsic.uncurry(intrinsic.promiseResolve);
|
|
29
32
|
/** @internal The RECEIVER for the captured `Promise.resolve`, captured too. `resolve` builds through
|
|
@@ -108,8 +111,8 @@ var KNOWN_REVOKED_KEYS = intrinsic.assign(intrinsic.create(null), {
|
|
|
108
111
|
});
|
|
109
112
|
|
|
110
113
|
var REQUIRED_CRITICALITY = intrinsic.create(null);
|
|
111
|
-
[["cRLNumber", false], ["authorityKeyIdentifier", false], ["freshestCRL", false], ["authorityInfoAccess", false],
|
|
112
|
-
["issuingDistributionPoint", true], ["deltaCRLIndicator", true]]
|
|
114
|
+
intrinsic.forEach([["cRLNumber", false], ["authorityKeyIdentifier", false], ["freshestCRL", false], ["authorityInfoAccess", false],
|
|
115
|
+
["issuingDistributionPoint", true], ["deltaCRLIndicator", true]], function (r) { REQUIRED_CRITICALITY[O(r[0])] = r[1]; });
|
|
113
116
|
|
|
114
117
|
var REQUIRED_ENTRY_CRITICALITY = intrinsic.create(null);
|
|
115
118
|
(function () {
|
|
@@ -184,11 +187,11 @@ function _idpValue(idp) {
|
|
|
184
187
|
if (idp.fullName != null) {
|
|
185
188
|
var entries = Array.isArray(idp.fullName) ? pkiBuild.reqDenseArray(idp.fullName, "issuingDistributionPoint.fullName", _err, "crl/bad-idp") : [idp.fullName];
|
|
186
189
|
if (!entries.length) throw _err("crl/bad-idp", "issuingDistributionPoint fullName must carry at least one GeneralName");
|
|
187
|
-
children
|
|
190
|
+
_push(children,b.contextConstructed(0, b.contextConstructed(0, Buffer.concat(entries.map(_encodeGeneralName)))));
|
|
188
191
|
}
|
|
189
192
|
var scopeTrue = 0;
|
|
190
|
-
if (idp.onlyContainsUserCerts === true) { children
|
|
191
|
-
if (idp.onlyContainsCACerts === true) { children
|
|
193
|
+
if (idp.onlyContainsUserCerts === true) { _push(children,b.contextPrimitive(1, Buffer.from([0xff]))); scopeTrue++; }
|
|
194
|
+
if (idp.onlyContainsCACerts === true) { _push(children,b.contextPrimitive(2, Buffer.from([0xff]))); scopeTrue++; }
|
|
192
195
|
if (idp.indirectCRL === true) throw _err("crl/bad-idp", _INDIRECT_IDP_DEFERRED);
|
|
193
196
|
if (scopeTrue > 1) throw _err("crl/bad-idp", "at most one of onlyContainsUserCerts / onlyContainsCACerts may be TRUE (RFC 5280 sec. 5.2.5)");
|
|
194
197
|
if (!children.length) throw _err("crl/bad-idp", "issuingDistributionPoint MUST NOT be empty (RFC 5280 sec. 5.2.5)");
|
|
@@ -199,7 +202,7 @@ var _PRE_ENCODED_IDP_SCHEMA = pkix.issuingDistributionPoint("crl/bad-idp");
|
|
|
199
202
|
function _validatePreEncodedIdp(inner) {
|
|
200
203
|
if (!inner.children || !inner.children.length) throw _err("crl/bad-idp", "pre-encoded issuingDistributionPoint MUST NOT be empty (RFC 5280 sec. 5.2.5)");
|
|
201
204
|
var f = schema.walk(_PRE_ENCODED_IDP_SCHEMA, inner, NS).fields;
|
|
202
|
-
["onlyContainsUserCerts", "onlyContainsCACerts", "onlyContainsAttributeCerts"]
|
|
205
|
+
intrinsic.forEach(["onlyContainsUserCerts", "onlyContainsCACerts", "onlyContainsAttributeCerts"], function (name) {
|
|
203
206
|
if (f[name].present && f[name].value !== true) throw _err("crl/bad-idp", "pre-encoded issuingDistributionPoint " + name + " encodes its DEFAULT FALSE, which DER omits (X.690 sec. 11.5)");
|
|
204
207
|
});
|
|
205
208
|
if (f.indirectCRL.present) throw _err("crl/bad-idp", _INDIRECT_IDP_DEFERRED);
|
|
@@ -232,7 +235,7 @@ function _buildCrlExtensions(spec, ctx) {
|
|
|
232
235
|
var id = O(oidName);
|
|
233
236
|
if (seen[id]) throw _err("crl/bad-input", "duplicate CRL extension " + oidName + " (RFC 5280 sec. 5.2 -- at most one instance)");
|
|
234
237
|
seen[id] = true;
|
|
235
|
-
out
|
|
238
|
+
_push(out,_ext(id, critical, valueDer));
|
|
236
239
|
}
|
|
237
240
|
var crlNumberVal = null;
|
|
238
241
|
if (spec.crlNumber != null) { var cn = _boundedInteger(spec.crlNumber, "cRLNumber"); crlNumberVal = cn.value; push("cRLNumber", false, cn.tlv); }
|
|
@@ -264,7 +267,7 @@ function _buildCrlExtensions(spec, ctx) {
|
|
|
264
267
|
}
|
|
265
268
|
_assertExtensionValueDecodes(node, extnId, "extension");
|
|
266
269
|
if (extnId === O("deltaCRLIndicator")) isDelta = true;
|
|
267
|
-
out
|
|
270
|
+
_push(out,b.raw(der));
|
|
268
271
|
});
|
|
269
272
|
if (isDelta) {
|
|
270
273
|
if (seen[O("freshestCRL")]) throw _err("crl/bad-input", "freshestCRL MUST NOT appear in a delta CRL (RFC 5280 sec. 5.2.6)");
|
|
@@ -323,7 +326,7 @@ function _buildRevoked(entryList, isDelta) {
|
|
|
323
326
|
var id = O(oidName);
|
|
324
327
|
if (seen[id]) throw _err("crl/bad-input", "duplicate entry extension " + oidName + " in revoked entry [" + idx + "]");
|
|
325
328
|
seen[id] = true;
|
|
326
|
-
entryExts
|
|
329
|
+
_push(entryExts,_ext(id, critical, valueDer));
|
|
327
330
|
}
|
|
328
331
|
if (e.reason != null) {
|
|
329
332
|
var codeNum = _resolveReason(e.reason, isDelta);
|
|
@@ -360,10 +363,10 @@ function _buildRevoked(entryList, isDelta) {
|
|
|
360
363
|
}
|
|
361
364
|
}
|
|
362
365
|
_assertExtensionValueDecodes(xnode, extnId, "entry extension");
|
|
363
|
-
entryExts
|
|
366
|
+
_push(entryExts,b.raw(der));
|
|
364
367
|
});
|
|
365
368
|
}
|
|
366
|
-
if (entryExts.length) { anyExt = true; children
|
|
369
|
+
if (entryExts.length) { anyExt = true; _push(children,b.sequence(entryExts)); }
|
|
367
370
|
return b.sequence(children);
|
|
368
371
|
});
|
|
369
372
|
return { entries: entries, anyExt: anyExt };
|
|
@@ -375,7 +378,11 @@ function _parseIssuerCert(cert) {
|
|
|
375
378
|
}
|
|
376
379
|
|
|
377
380
|
function _assertIssuerCanSignCrl(issuerCert) {
|
|
378
|
-
|
|
381
|
+
/** @internal The selection returns the first matching row or null. `filter(...)[0]` indexes a
|
|
382
|
+
* result that is EMPTY when the certificate carries no keyUsage, and index 0 of an empty array
|
|
383
|
+
* answers from the array prototype, so a value installed there would be decoded as the issuer's
|
|
384
|
+
* key usage and decide whether it may sign this CRL. */
|
|
385
|
+
var kuExt = guard.list.firstMatch(issuerCert.extensions || [], function (e) { return e.oid === O("keyUsage"); });
|
|
379
386
|
if (!kuExt) return;
|
|
380
387
|
var ku;
|
|
381
388
|
try { ku = EXT_DECODERS[O("keyUsage")](kuExt.value); }
|
|
@@ -453,13 +460,13 @@ function _sign(spec, issuer, opts) {
|
|
|
453
460
|
* into the PreTBSCertList the alternative signature covers. */
|
|
454
461
|
function tbsOver(extList, omitSignatureAlg) {
|
|
455
462
|
var tbsChildren = [];
|
|
456
|
-
if (version === 2) tbsChildren
|
|
457
|
-
if (omitSignatureAlg !== true) tbsChildren
|
|
458
|
-
tbsChildren
|
|
459
|
-
tbsChildren
|
|
460
|
-
if (nextU) tbsChildren
|
|
461
|
-
if (revoked.entries.length) tbsChildren
|
|
462
|
-
if (extList.length) tbsChildren
|
|
463
|
+
if (version === 2) _push(tbsChildren,b.integer(1n));
|
|
464
|
+
if (omitSignatureAlg !== true) _push(tbsChildren,scheme.sigAlgId);
|
|
465
|
+
_push(tbsChildren,issuerDer);
|
|
466
|
+
_push(tbsChildren,thisU);
|
|
467
|
+
if (nextU) _push(tbsChildren,nextU);
|
|
468
|
+
if (revoked.entries.length) _push(tbsChildren,b.sequence(revoked.entries));
|
|
469
|
+
if (extList.length) _push(tbsChildren,b.explicit(0, b.sequence(extList)));
|
|
463
470
|
return b.sequence(tbsChildren);
|
|
464
471
|
}
|
|
465
472
|
|
|
@@ -813,7 +820,7 @@ function isRevoked(crl, serialNumber, opts) {
|
|
|
813
820
|
|
|
814
821
|
function _findExtOid(list, name) {
|
|
815
822
|
var want = O(name);
|
|
816
|
-
return (list || []
|
|
823
|
+
return guard.list.firstMatch(list || [], function (e) { return e.oid === want; });
|
|
817
824
|
}
|
|
818
825
|
|
|
819
826
|
var _IDP_SCHEMA = pkix.issuingDistributionPoint("crl/scope-not-authoritative");
|
package/lib/csr-sign.js
CHANGED
|
@@ -26,6 +26,9 @@ var pkiBuild = require("./pki-build");
|
|
|
26
26
|
var frameworkError = require("./framework-error");
|
|
27
27
|
var guard = require("./guard-all");
|
|
28
28
|
var intrinsic = require("./guard-intrinsic");
|
|
29
|
+
/** @internal The append every list here is built with: `push` stores at the index and a store
|
|
30
|
+
* consults a setter inherited there, and these lists become the bytes that get signed. */
|
|
31
|
+
var _push = intrinsic.append;
|
|
29
32
|
/** @internal The promise a self-check is awaited through, built from the constructor captured at load.
|
|
30
33
|
* `Promise.resolve` builds from its RECEIVER, so reading the global binding at the call hands the
|
|
31
34
|
* construction to whatever that binding holds, and a constructor settling without awaiting its
|
|
@@ -224,7 +227,7 @@ function _sign(spec, key, opts) {
|
|
|
224
227
|
function addAttr(attrType, valueTlv) {
|
|
225
228
|
if (seenAttr[attrType]) throw _err("csr/bad-input", "duplicate " + (oid.name(attrType) || attrType) + " attribute");
|
|
226
229
|
seenAttr[attrType] = true;
|
|
227
|
-
attrs
|
|
230
|
+
_push(attrs,b.sequence([b.oid(attrType), b.set([valueTlv])]));
|
|
228
231
|
}
|
|
229
232
|
if (spec.extensionRequest != null) addAttr(O("extensionRequest"), _buildRequestedExtensions(spec.extensionRequest, subjectSpki));
|
|
230
233
|
if (spec.challengePassword != null) addAttr(O("challengePassword"), _challengePassword(spec.challengePassword));
|
|
@@ -259,7 +262,7 @@ function _sign(spec, key, opts) {
|
|
|
259
262
|
if (!n.children[1].children || n.children[1].children.length === 0) throw _err("csr/bad-input", "pre-encoded attribute [" + i + "] value SET must contain at least one value (RFC 2986 SET SIZE(1..MAX))");
|
|
260
263
|
if (seenAttr[at]) throw _err("csr/bad-input", "duplicate " + (oid.name(at) || at) + " attribute");
|
|
261
264
|
seenAttr[at] = true;
|
|
262
|
-
attrs
|
|
265
|
+
_push(attrs,b.raw(der));
|
|
263
266
|
});
|
|
264
267
|
}
|
|
265
268
|
|
package/lib/ct.js
CHANGED
|
@@ -63,6 +63,8 @@ var _bufToString = intrinsic.bufToString;
|
|
|
63
63
|
var _bufferCompare = intrinsic.compare;
|
|
64
64
|
var _subarray = intrinsic.subarray;
|
|
65
65
|
var _toLowerCase = intrinsic.toLowerCase;
|
|
66
|
+
var _ctTrim = intrinsic.uncurry(String.prototype.trim);
|
|
67
|
+
var _writeBigUInt64BE = intrinsic.uncurry(Buffer.prototype.writeBigUInt64BE);
|
|
66
68
|
var _bufCopy = intrinsic.uncurry(Buffer.prototype.copy);
|
|
67
69
|
var _writeU64BE = intrinsic.uncurry(Buffer.prototype.writeBigUInt64BE);
|
|
68
70
|
var _searchSet = intrinsic.uncurry(URLSearchParams.prototype.set);
|
|
@@ -292,8 +294,11 @@ function parseSctList(extValue) {
|
|
|
292
294
|
}
|
|
293
295
|
sctCount.tick();
|
|
294
296
|
var one = _parseSct(outer.subReader(sctLen, "ct/list-trailing-bytes"), sctLen);
|
|
295
|
-
|
|
296
|
-
|
|
297
|
+
/** @internal The parsed timestamps are appended by defining their indexes: the lists a caller
|
|
298
|
+
* reads its verdict from, and the `all` list a policy counts, are what a numeric setter on the
|
|
299
|
+
* array prototype would otherwise take an entry out of. */
|
|
300
|
+
if (one.unknown) { var u = { version: one.version, rawSct: one.rawSct }; intrinsic.append(unknownScts, u); intrinsic.append(all, u); }
|
|
301
|
+
else { intrinsic.append(scts, one); intrinsic.append(all, one); }
|
|
297
302
|
}
|
|
298
303
|
return guard.verdict.of({ scts: scts, unknownScts: unknownScts, all: all });
|
|
299
304
|
}
|
|
@@ -365,29 +370,36 @@ function reconstructSignedData(entry, sct) {
|
|
|
365
370
|
throw new CtError("ct/bad-input", "reconstructSignedData expects a decoded v1 SCT from parseSctList().scts[]");
|
|
366
371
|
}
|
|
367
372
|
var tsVal = guard.range.uint64(sct.timestamp, _ctErr, "ct/bad-input", "sct.timestamp (RFC 6962 3.2)");
|
|
373
|
+
/** @internal EVERY component of this preimage is appended by defining its index, and the
|
|
374
|
+
* concatenation is the captured one. These bytes are what a log's signature is verified over, so a
|
|
375
|
+
* numeric setter inherited from the array prototype replacing any one of them, the version, the
|
|
376
|
+
* signature type, the timestamp, the entry type, the certificate or the extensions, puts the
|
|
377
|
+
* verification on bytes the log never signed. Converting only the timestamp left the rest open,
|
|
378
|
+
* which is the whole class: the rule belongs to the function, not to the line it was found on. */
|
|
368
379
|
var parts = [];
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
var ts = _bufferAlloc(8); ts
|
|
372
|
-
|
|
380
|
+
intrinsic.append(parts, _bufferFrom([sct.version & 0xff]));
|
|
381
|
+
intrinsic.append(parts, _bufferFrom([0]));
|
|
382
|
+
var ts = _bufferAlloc(8); _writeBigUInt64BE(ts, tsVal); intrinsic.append(parts, ts);
|
|
383
|
+
intrinsic.append(parts, _bufferFrom([(entryType >> 8) & 0xff, entryType & 0xff]));
|
|
373
384
|
if (entryType === 0) {
|
|
374
385
|
var cert = _toBuffer(entry.leafCert, "leafCert", undefined, undefined, 0xffffff, "ct/bad-tbs-length");
|
|
375
|
-
|
|
386
|
+
intrinsic.append(parts, _u24Bytes(cert.length)); intrinsic.append(parts, cert);
|
|
376
387
|
} else {
|
|
377
388
|
var ikh = _toBuffer(entry.issuerKeyHash, "issuerKeyHash");
|
|
378
389
|
if (ikh.length !== 32) {
|
|
379
390
|
throw new CtError("ct/bad-issuer-key-hash", "issuer_key_hash must be exactly 32 bytes (SHA-256 of the issuer SPKI), got " + ikh.length + " (RFC 6962 sec. 3.2)");
|
|
380
391
|
}
|
|
381
392
|
var tbs = _toBuffer(entry.tbsCertificate, "tbsCertificate", undefined, undefined, 0xffffff, "ct/bad-tbs-length");
|
|
382
|
-
|
|
383
|
-
|
|
393
|
+
intrinsic.append(parts, ikh);
|
|
394
|
+
intrinsic.append(parts, _u24Bytes(tbs.length)); intrinsic.append(parts, tbs);
|
|
384
395
|
}
|
|
385
396
|
var ext = _toBuffer(sct.extensions, "sct.extensions", undefined, undefined, 0xffff, "ct/bad-extensions");
|
|
386
397
|
if (ext.length > 0xffff) {
|
|
387
398
|
throw new CtError("ct/bad-extensions", "CtExtensions must be 0..65535 bytes, got " + ext.length + " (RFC 6962 3.2)");
|
|
388
399
|
}
|
|
389
|
-
|
|
390
|
-
|
|
400
|
+
intrinsic.append(parts, _bufferFrom([(ext.length >> 8) & 0xff, ext.length & 0xff]));
|
|
401
|
+
intrinsic.append(parts, ext);
|
|
402
|
+
return intrinsic.bufferConcat(parts);
|
|
391
403
|
}
|
|
392
404
|
|
|
393
405
|
var CT_HASH = intrinsic.assign(intrinsic.create(null), { sha256: "SHA-256" });
|
|
@@ -583,7 +595,7 @@ function encodeSctList(scts) {
|
|
|
583
595
|
var el = ew.build();
|
|
584
596
|
total += el.length;
|
|
585
597
|
if (total > 0xffff) throw new CtError("ct/too-large", "the SCT list body exceeds the 65535-byte maximum (RFC 6962 sec. 3.3)");
|
|
586
|
-
|
|
598
|
+
intrinsic.append(elements, el);
|
|
587
599
|
}
|
|
588
600
|
var lw = new TlsWriter();
|
|
589
601
|
lw.vector(2, 1, 0xffff, Buffer.concat(elements, total), "ct/too-large");
|
|
@@ -802,7 +814,7 @@ function parseLogList(json, opts) {
|
|
|
802
814
|
continue;
|
|
803
815
|
}
|
|
804
816
|
byLogId[rec.logIdHex] = rec;
|
|
805
|
-
|
|
817
|
+
intrinsic.append(logs, rec);
|
|
806
818
|
}
|
|
807
819
|
}
|
|
808
820
|
}
|
|
@@ -1091,13 +1103,13 @@ function x509CertEntry(cert, issuer) {
|
|
|
1091
1103
|
for (var j = 0; j < extsSeq.children.length; j++) {
|
|
1092
1104
|
var ext = extsSeq.children[j];
|
|
1093
1105
|
if (ext.children[0] && intrinsic.bufferEquals(ext.children[0].bytes, sctOid)) { removed++; continue; }
|
|
1094
|
-
intrinsic.
|
|
1106
|
+
intrinsic.append(kept, ext.bytes);
|
|
1095
1107
|
}
|
|
1096
1108
|
if (removed === 0) throw _ctErr("ct/no-sct-extension", "the certificate carries no signedCertificateTimestampList extension (RFC 6962 sec. 3.2)");
|
|
1097
1109
|
var tbsChildren = [];
|
|
1098
1110
|
for (var k = 0; k < tbs.children.length; k++) {
|
|
1099
|
-
if (k !== wrapIdx) { intrinsic.
|
|
1100
|
-
if (kept.length > 0) intrinsic.
|
|
1111
|
+
if (k !== wrapIdx) { intrinsic.append(tbsChildren, tbs.children[k].bytes); continue; }
|
|
1112
|
+
if (kept.length > 0) intrinsic.append(tbsChildren, asn1.build.explicit(3, asn1.build.sequence(kept)));
|
|
1101
1113
|
}
|
|
1102
1114
|
var issuerKeyHash = nodeCrypto.createHash("sha256").update(issSpki).digest();
|
|
1103
1115
|
return { entryType: 1, tbsCertificate: asn1.build.sequence(tbsChildren), issuerKeyHash: issuerKeyHash };
|
|
@@ -1230,7 +1242,15 @@ function _assertTransport(opts) {
|
|
|
1230
1242
|
"(request) => Promise<{ status, headers, body }>");
|
|
1231
1243
|
}
|
|
1232
1244
|
|
|
1233
|
-
|
|
1245
|
+
/** @internal The media type is read through the captured operations, and on the delimiter CHARACTER
|
|
1246
|
+
* rather than through `split`, which hard rule 11 bans in lib/ because the separator's own
|
|
1247
|
+
* `Symbol.split` is part of that operation. The token decides which parser a log's response body is
|
|
1248
|
+
* handed to. */
|
|
1249
|
+
function _fetchCtypeToken(headers) {
|
|
1250
|
+
var raw = intrinsic.String((headers || {})["content-type"] || "");
|
|
1251
|
+
var parts = intrinsic.splitChar(raw, 59);
|
|
1252
|
+
return _toLowerCase(_ctTrim(parts.length ? parts[0] : ""));
|
|
1253
|
+
}
|
|
1234
1254
|
|
|
1235
1255
|
function _parseHttpsUrl(u, label) {
|
|
1236
1256
|
var parsed;
|
package/lib/est.js
CHANGED
|
@@ -73,9 +73,15 @@ var crmfFmt = require("./schema-crmf");
|
|
|
73
73
|
var frameworkError = require("./framework-error");
|
|
74
74
|
var guard = require("./guard-all");
|
|
75
75
|
var intrinsic = require("./guard-intrinsic");
|
|
76
|
+
/** @internal The append every list here is built with: `push` stores at the index and a store
|
|
77
|
+
* consults a setter inherited there, which takes the element being appended. */
|
|
78
|
+
var _push = intrinsic.append;
|
|
76
79
|
var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
|
|
77
80
|
var _strSlice = intrinsic.uncurry(String.prototype.slice);
|
|
78
81
|
var _toLowerCase = intrinsic.uncurry(String.prototype.toLowerCase);
|
|
82
|
+
var _estTrim = intrinsic.uncurry(String.prototype.trim);
|
|
83
|
+
var _estCharAt = intrinsic.uncurry(String.prototype.charAt);
|
|
84
|
+
var _estIndexOf = intrinsic.stringIndexOf;
|
|
79
85
|
/** @internal Each verb gates its body on a resolved promise and returns its refusals as rejected ones,
|
|
80
86
|
* and both build from the RECEIVER, so reading the global binding at the call decides whether the body
|
|
81
87
|
* runs and whether a refusal stays a refusal. Taken at load. */
|
|
@@ -250,7 +256,7 @@ function _isMultipartMixedPrefix(ct) {
|
|
|
250
256
|
}
|
|
251
257
|
|
|
252
258
|
function _multipartBoundary(contentType) {
|
|
253
|
-
var ct =
|
|
259
|
+
var ct = _stringOf(contentType || "");
|
|
254
260
|
if (!_isMultipartMixedPrefix(ct)) return null;
|
|
255
261
|
var bp = _ctParam(ct, "boundary");
|
|
256
262
|
if (bp.duplicated) {
|
|
@@ -356,12 +362,16 @@ function splitMultipartMixed(body, contentType) {
|
|
|
356
362
|
var lines = _splitCrlf(_unfoldHeaders(rawHeaders));
|
|
357
363
|
for (var li = 0; li < lines.length; li++) {
|
|
358
364
|
var line = lines[li];
|
|
359
|
-
|
|
360
|
-
|
|
365
|
+
/** @internal A part's header name and value are cut, trimmed and folded through the captured
|
|
366
|
+
* operations. One of those headers is the part's own content type, which selects the reader
|
|
367
|
+
* its body goes to: measured, a part stating `application/pkcs8` was read as
|
|
368
|
+
* `application/pkcs7-mime` with a `smime-type` of `certs-only`. */
|
|
369
|
+
var col = _estIndexOf(line, ":");
|
|
370
|
+
if (col > 0) headers[_toLowerCase(_estTrim(_strSlice(line, 0, col)))] = _estTrim(_strSlice(line, col + 1));
|
|
361
371
|
}
|
|
362
372
|
var partCt = headers["content-type"] || "";
|
|
363
373
|
if (_ciStartsWith(partCt, "MULTIPART/")) throw E("est/bad-multipart", "a nested multipart part is not permitted");
|
|
364
|
-
|
|
374
|
+
intrinsic.append(parts, { headers: headers, contentType: partCt, body: partBody });
|
|
365
375
|
}
|
|
366
376
|
return parts;
|
|
367
377
|
}
|
|
@@ -416,7 +426,7 @@ function findIssuedCert(certs, target) {
|
|
|
416
426
|
|
|
417
427
|
function _recipientKeyIds(recipientInfos, kind) {
|
|
418
428
|
var ids = [];
|
|
419
|
-
function push(v) { if (Buffer.isBuffer(v)) ids
|
|
429
|
+
function push(v) { if (Buffer.isBuffer(v)) _push(ids,v); }
|
|
420
430
|
(recipientInfos || []).forEach(function (r) {
|
|
421
431
|
if (kind !== "symmetric") {
|
|
422
432
|
if (r.rid) push(r.rid.subjectKeyIdentifier);
|
|
@@ -432,7 +442,7 @@ function _recipientKeyIds(recipientInfos, kind) {
|
|
|
432
442
|
|
|
433
443
|
function _recipientIssuerSerials(recipientInfos) {
|
|
434
444
|
var out = [];
|
|
435
|
-
function push(rid) { if (rid && rid.issuer && Buffer.isBuffer(rid.issuer.bytes) && rid.serialNumber != null) out
|
|
445
|
+
function push(rid) { if (rid && rid.issuer && Buffer.isBuffer(rid.issuer.bytes) && rid.serialNumber != null) _push(out,{ issuer: rid.issuer.bytes, serialNumber: rid.serialNumber }); }
|
|
436
446
|
(recipientInfos || []).forEach(function (r) {
|
|
437
447
|
push(r.rid);
|
|
438
448
|
if (r.kemri) push(r.kemri.rid);
|
|
@@ -457,29 +467,37 @@ function _recipientMatches(recipientInfos, opts) {
|
|
|
457
467
|
return false;
|
|
458
468
|
}
|
|
459
469
|
|
|
470
|
+
/** @internal The segments are collected through the captured append. Read off the prototype, a
|
|
471
|
+
* replacement decides which segments a parameter is then looked for in, and one of those parameters
|
|
472
|
+
* is the multipart boundary a response body is divided on: measured, a `boundary=wire` header
|
|
473
|
+
* yielded `forged`. */
|
|
460
474
|
function _splitContentTypeParams(s) {
|
|
461
475
|
var segs = [], cur = "", inQuote = false;
|
|
462
476
|
for (var i = 0; i < s.length; i++) {
|
|
463
|
-
var ch = s
|
|
477
|
+
var ch = _estCharAt(s, i);
|
|
464
478
|
if (ch === '"') { inQuote = !inQuote; cur += ch; }
|
|
465
|
-
else if (ch === ";" && !inQuote) {
|
|
479
|
+
else if (ch === ";" && !inQuote) { intrinsic.append(segs, cur); cur = ""; }
|
|
466
480
|
else cur += ch;
|
|
467
481
|
}
|
|
468
|
-
|
|
482
|
+
intrinsic.append(segs, cur);
|
|
469
483
|
return segs;
|
|
470
484
|
}
|
|
471
485
|
|
|
472
486
|
function _ctParam(contentType, name) {
|
|
473
|
-
var segs = _splitContentTypeParams(
|
|
487
|
+
var segs = _splitContentTypeParams(_stringOf(contentType || ""));
|
|
474
488
|
var value = null, count = 0;
|
|
489
|
+
/** @internal Each parameter is read through the captured operations. The name decides which
|
|
490
|
+
* parameter this is, and the value it returns is the one a caller acts on: for the RFC 7030
|
|
491
|
+
* multipart boundary, it is where a response body is split. */
|
|
475
492
|
for (var i = 1; i < segs.length; i++) {
|
|
476
|
-
var
|
|
493
|
+
var seg = segs[i];
|
|
494
|
+
var eq = _estIndexOf(seg, "=");
|
|
477
495
|
if (eq === -1) continue;
|
|
478
|
-
if (
|
|
496
|
+
if (_toLowerCase(_estTrim(_strSlice(seg, 0, eq))) !== name) continue;
|
|
479
497
|
count++;
|
|
480
498
|
if (count > 1) continue;
|
|
481
|
-
var val =
|
|
482
|
-
if (val.length >= 2 && val
|
|
499
|
+
var val = _estTrim(_strSlice(seg, eq + 1));
|
|
500
|
+
if (val.length >= 2 && _estCharAt(val, 0) === '"' && _estCharAt(val, val.length - 1) === '"') val = _strSlice(val, 1, -1);
|
|
483
501
|
value = val;
|
|
484
502
|
}
|
|
485
503
|
return { value: value, duplicated: count > 1 };
|
|
@@ -501,12 +519,15 @@ function _mediaType(seg) {
|
|
|
501
519
|
return _toLowerCase(_strSlice(seg, a, b));
|
|
502
520
|
}
|
|
503
521
|
|
|
522
|
+
/** @internal The media type and the S/MIME type are produced through the captured conversions. The
|
|
523
|
+
* media type selects which reader a part's body goes to, and read through the live global `String`
|
|
524
|
+
* a replacement chose it: measured, `text/plain` arrived as `application/pkcs8`. */
|
|
504
525
|
function _partMediaType(contentType) {
|
|
505
|
-
var segs = _splitContentTypeParams(
|
|
526
|
+
var segs = _splitContentTypeParams(_stringOf(contentType || ""));
|
|
506
527
|
var st = _ctParam(contentType, "smime-type");
|
|
507
528
|
return {
|
|
508
529
|
media: _mediaType(segs[0]),
|
|
509
|
-
smimeType: st.value === null ? null : st.value
|
|
530
|
+
smimeType: st.value === null ? null : _toLowerCase(st.value),
|
|
510
531
|
ambiguous: st.duplicated,
|
|
511
532
|
};
|
|
512
533
|
}
|
|
@@ -740,7 +761,7 @@ function smimeCapabilitiesAttr(capabilities) {
|
|
|
740
761
|
if (!Array.isArray(capabilities) || capabilities.length === 0) throw E("est/bad-input", "smimeCapabilitiesAttr requires a non-empty capability list");
|
|
741
762
|
var caps = capabilities.map(function (c) {
|
|
742
763
|
var seq = [asn1.build.oid(c.capabilityID)];
|
|
743
|
-
if (c.parameters !== undefined && c.parameters !== null) seq
|
|
764
|
+
if (c.parameters !== undefined && c.parameters !== null) _push(seq,Buffer.isBuffer(c.parameters) ? c.parameters : asn1.build.oid(c.parameters));
|
|
744
765
|
return asn1.build.sequence(seq);
|
|
745
766
|
});
|
|
746
767
|
return _attr(OID_SMIME_CAPABILITIES, [asn1.build.sequence(caps)]);
|
|
@@ -762,7 +783,7 @@ function buildEnrollAttributes(csrattrsParsed) {
|
|
|
762
783
|
if (plan.keyType) throw E("est/ambiguous-key-type", "a non-template CsrAttrs response must carry exactly one key-type attribute (RFC 9908 sec. 3.2)");
|
|
763
784
|
plan.keyType = { type: it.name, curve: it.curve || null, keySize: it.keySize || null, values: it.values || [] };
|
|
764
785
|
}
|
|
765
|
-
else plan.unhandled
|
|
786
|
+
else _push(plan.unhandled,{ kind: it.kind, oid: it.oid, name: it.name });
|
|
766
787
|
}
|
|
767
788
|
return plan;
|
|
768
789
|
}
|
|
@@ -1199,7 +1220,7 @@ function _correlateIssued(bag, wanted, arm) {
|
|
|
1199
1220
|
function _allMatching(bag, key) {
|
|
1200
1221
|
var rest = bag.slice(), out = [], hit;
|
|
1201
1222
|
while ((hit = findIssuedCert(rest, key)) !== null) {
|
|
1202
|
-
out
|
|
1223
|
+
_push(out,hit);
|
|
1203
1224
|
rest = rest.filter(function (c) { return c !== hit; });
|
|
1204
1225
|
}
|
|
1205
1226
|
return out;
|
|
@@ -1222,7 +1243,7 @@ function _requestedPublicKeys(der) {
|
|
|
1222
1243
|
try {
|
|
1223
1244
|
if (r.certificationRequestBytes) {
|
|
1224
1245
|
var spki = csr.parse(r.certificationRequestBytes).subjectPublicKeyInfo;
|
|
1225
|
-
if (spki && Buffer.isBuffer(spki.bytes)) out
|
|
1246
|
+
if (spki && Buffer.isBuffer(spki.bytes)) _push(out,spki.bytes);
|
|
1226
1247
|
if (out.length === before) _unreadableArm();
|
|
1227
1248
|
return;
|
|
1228
1249
|
}
|
|
@@ -1233,7 +1254,7 @@ function _requestedPublicKeys(der) {
|
|
|
1233
1254
|
var pk = (tmpl && tmpl.publicKey) ||
|
|
1234
1255
|
(msg0 && msg0.popo && msg0.popo.poposkInput && msg0.popo.poposkInput.publicKey);
|
|
1235
1256
|
var pkBytes = Buffer.isBuffer(pk) ? pk : (pk && pk.bytes);
|
|
1236
|
-
if (Buffer.isBuffer(pkBytes)) out
|
|
1257
|
+
if (Buffer.isBuffer(pkBytes)) _push(out,pkBytes);
|
|
1237
1258
|
if (out.length === before) _unreadableArm();
|
|
1238
1259
|
}
|
|
1239
1260
|
} catch (e) {
|
|
@@ -1279,9 +1300,9 @@ function _requestBinding(der) {
|
|
|
1279
1300
|
var body = cmcFmt.parse(der);
|
|
1280
1301
|
var ids = [];
|
|
1281
1302
|
var paths = [];
|
|
1282
|
-
[body.requests, body.controls, body.cmsSequence, body.otherMsgs]
|
|
1303
|
+
intrinsic.forEach([body.requests, body.controls, body.cmsSequence, body.otherMsgs], function (list) {
|
|
1283
1304
|
(list || []).forEach(function (el) {
|
|
1284
|
-
if (el && el.bodyPartID != null) { ids
|
|
1305
|
+
if (el && el.bodyPartID != null) { _push(ids,el.bodyPartID); _push(paths,[el.bodyPartID]); }
|
|
1285
1306
|
});
|
|
1286
1307
|
});
|
|
1287
1308
|
_collectNestedPaths(body.cmsSequence, [], paths, 0);
|
|
@@ -1325,8 +1346,8 @@ function _collectNestedPaths(list, prefix, out, depth) {
|
|
|
1325
1346
|
catch (_e) { /* allow:swallow-unverified the outer request must itself parse for this to run, which already rejects a malformed nested ContentInfo; a payload that survives that and still fails to read back lands on the same no-path refusal the non-pkiData route below takes, which the vectors drive */ return; }
|
|
1326
1347
|
if (!inner || inner.kind !== "pkiData") return;
|
|
1327
1348
|
var path = prefix.concat([el.bodyPartID]);
|
|
1328
|
-
[inner.requests, inner.controls, inner.cmsSequence, inner.otherMsgs]
|
|
1329
|
-
(l || []).forEach(function (e2) { if (e2 && e2.bodyPartID != null) out
|
|
1349
|
+
intrinsic.forEach([inner.requests, inner.controls, inner.cmsSequence, inner.otherMsgs], function (l) {
|
|
1350
|
+
(l || []).forEach(function (e2) { if (e2 && e2.bodyPartID != null) _push(out,path.concat([e2.bodyPartID])); });
|
|
1330
1351
|
});
|
|
1331
1352
|
_collectNestedPaths(inner.cmsSequence, path, out, depth + 1);
|
|
1332
1353
|
});
|
|
@@ -1405,7 +1426,7 @@ function _fullcmcResult(res, opts, wanted, sent) {
|
|
|
1405
1426
|
}
|
|
1406
1427
|
var smimeType = pt200.smimeType;
|
|
1407
1428
|
if (smimeType === "certs-only") {
|
|
1408
|
-
var unecho = ["transactionId", "senderNonce", "dataReturn"]
|
|
1429
|
+
var unecho = intrinsic.selectList(["transactionId", "senderNonce", "dataReturn"], function (k) {
|
|
1409
1430
|
return sent[k] != null;
|
|
1410
1431
|
});
|
|
1411
1432
|
if (unecho.length) {
|
|
@@ -1731,21 +1752,23 @@ function _assertConfidentialCipher(res) {
|
|
|
1731
1752
|
|
|
1732
1753
|
function _ciHeaderList(headers, name) {
|
|
1733
1754
|
headers = headers || {};
|
|
1734
|
-
|
|
1755
|
+
/** @internal The header NAME a value is selected under is folded through the captured conversion on
|
|
1756
|
+
* both sides of the comparison: the match decides which header this response is read from. */
|
|
1757
|
+
var lname = _toLowerCase(name), keys = guard.identifier.optionNames(headers), parts = [];
|
|
1735
1758
|
for (var i = 0; i < keys.length; i++) {
|
|
1736
|
-
if (keys[i]
|
|
1759
|
+
if (_toLowerCase(keys[i]) !== lname) continue;
|
|
1737
1760
|
var v = headers[keys[i]];
|
|
1738
1761
|
if (v == null) continue;
|
|
1739
|
-
|
|
1762
|
+
intrinsic.append(parts, intrinsic.isArray(v) ? intrinsic.join(v, ", ") : _stringOf(v));
|
|
1740
1763
|
}
|
|
1741
|
-
return parts.length ?
|
|
1764
|
+
return parts.length ? intrinsic.join(parts, ", ") : null;
|
|
1742
1765
|
}
|
|
1743
1766
|
|
|
1744
1767
|
function _ciHeader(headers, name) {
|
|
1745
1768
|
headers = headers || {};
|
|
1746
|
-
var lname = name
|
|
1769
|
+
var lname = _toLowerCase(name), keys = guard.identifier.optionNames(headers), found = null, n = 0;
|
|
1747
1770
|
for (var i = 0; i < keys.length; i++) {
|
|
1748
|
-
if (keys[i]
|
|
1771
|
+
if (_toLowerCase(keys[i]) !== lname) continue;
|
|
1749
1772
|
n += 1;
|
|
1750
1773
|
if (n === 1) found = headers[keys[i]];
|
|
1751
1774
|
}
|
package/lib/guard-bytes.js
CHANGED
|
@@ -446,7 +446,11 @@ function _deep(v, ErrorClass, code, label, cap, depth, collect, work) {
|
|
|
446
446
|
var element;
|
|
447
447
|
try { element = v[k]; }
|
|
448
448
|
catch (e) { throw _raise(ErrorClass, code, label + ": reading element " + k + " threw", e); }
|
|
449
|
-
|
|
449
|
+
/** @internal The copy's slot is DEFINED, not stored at. The indices walked here are the ones
|
|
450
|
+
* the source holds of its own, so they can skip: a store at an index this copy has no own
|
|
451
|
+
* property at walks the prototype chain for a setter, which would take the copied element at
|
|
452
|
+
* the toolkit's own door for caller byte structures. */
|
|
453
|
+
_defineProperty(arr, k, { value: _deep(element, ErrorClass, code, label, cap, depth + 1, collect, work), writable: true, enumerable: true, configurable: true });
|
|
450
454
|
});
|
|
451
455
|
arr.length = vCount;
|
|
452
456
|
_copyNamed(v, arr, ErrorClass, code, label, cap, depth, collect, work);
|
package/lib/guard-der.js
CHANGED
|
@@ -9,6 +9,7 @@ var _sizeOf = require("./guard-intrinsic").sizeOf;
|
|
|
9
9
|
var _create = require("./guard-intrinsic").create;
|
|
10
10
|
var _isBuffer = require("./guard-intrinsic").isBuffer;
|
|
11
11
|
var _isArray = require("./guard-intrinsic").isArray;
|
|
12
|
+
var _append = require("./guard-intrinsic").append;
|
|
12
13
|
|
|
13
14
|
var asn1 = null;
|
|
14
15
|
function _asn1() { if (asn1 === null) asn1 = require("./asn1-der"); return asn1; }
|
|
@@ -117,7 +118,11 @@ function _element(node, E, code, label) {
|
|
|
117
118
|
throw E(code, label + " of universal constructed type " + tag + " has no strict DER structure validator here");
|
|
118
119
|
}
|
|
119
120
|
var n = kids.length, members = [];
|
|
120
|
-
|
|
121
|
+
/** @internal Appended by defining the index. A store at an index the list has no own property at
|
|
122
|
+
* consults a setter inherited from the array prototype, and the SET ordering below is checked
|
|
123
|
+
* over this list, so a member read back through such a hole is one the canonical-order check
|
|
124
|
+
* never saw. */
|
|
125
|
+
for (var i = 0; i < n; i++) _append(members, _element(kids[i], E, code, label));
|
|
121
126
|
if (cls === "universal" && tag === C.SET && !setOrderOk(members)) {
|
|
122
127
|
throw E(code, label + " has a SET whose members are in no canonical DER order (X.690 sec. 11.6 / X.680 sec. 8.6)");
|
|
123
128
|
}
|
package/lib/guard-identifier.js
CHANGED
|
@@ -257,7 +257,7 @@ var _CONCRETE_TYPED_MEMBERS = ["BYTES_PER_ELEMENT"];
|
|
|
257
257
|
var _BUFFER_PROTO_MEMBERS = ["parent", "offset"];
|
|
258
258
|
|
|
259
259
|
var _ARRAY_MEMBERS = _ARRAY_PROTO_MEMBERS;
|
|
260
|
-
var _REGEXP_MEMBERS = ["lastIndex"]
|
|
260
|
+
var _REGEXP_MEMBERS = intrinsic.concatList(["lastIndex"], _REGEXP_PROTO_MEMBERS);
|
|
261
261
|
var _VIEW_MEMBERS = _TYPED_PROTO_MEMBERS.concat(_CONCRETE_TYPED_MEMBERS);
|
|
262
262
|
var _BUFFER_KIND_MEMBERS = _VIEW_MEMBERS.concat(_BUFFER_PROTO_MEMBERS);
|
|
263
263
|
var _DATAVIEW_MEMBERS = _DATAVIEW_PROTO_MEMBERS;
|
package/lib/guard-intrinsic.js
CHANGED
|
@@ -528,14 +528,24 @@ var _arrSort = uncurry(Array.prototype.sort);
|
|
|
528
528
|
var _arrConcat = uncurry(Array.prototype.concat);
|
|
529
529
|
var _arrSlice = uncurry(Array.prototype.slice);
|
|
530
530
|
var _arrJoin = uncurry(Array.prototype.join);
|
|
531
|
-
|
|
531
|
+
/** @internal `push` is NOT captured and NOT offered. Capturing it closes who `push` is, not what
|
|
532
|
+
* `push` DOES: it STORES at the index, and a store walks the prototype chain for a setter, so an
|
|
533
|
+
* accessor installed at an array index receives each element as it is appended and can define
|
|
534
|
+
* something else in its place. Measured through `pki.asn1.read.oid`: the content octets of `1.2.3`
|
|
535
|
+
* rendered `0.1.3` through a captured push. `append` below defines the index on the array itself,
|
|
536
|
+
* and `concatList` / `copyList` / `selectList` / `mapList` build their results the same way. With
|
|
537
|
+
* nothing to reach for, no module in lib/ can take the storing form. */
|
|
532
538
|
/** @internal The mutators. A list is what a rule is enforced over, so an operation that drops or moves
|
|
533
539
|
* an element decides whether the rule reaches it: a replaced `pop` that popped twice took a signed
|
|
534
540
|
* note's last signature line away with the empty tail element, and the forged signature on that line
|
|
535
541
|
* was never checked. */
|
|
542
|
+
/** @internal `unshift` is absent for the reason `push` is: it GROWS the list, so it stores at an
|
|
543
|
+
* index the array has no own property at, and a store walks the prototype chain for a setter. The
|
|
544
|
+
* mutators kept below move or drop elements that already have own slots, which reaches no accessor
|
|
545
|
+
* on a list this toolkit built by defining. A module prepending to a list counts its elements and
|
|
546
|
+
* appends them in order instead; `encodeLength` and `intToDer` in lib/asn1-der.js are the pattern. */
|
|
536
547
|
var _arrPop = uncurry(Array.prototype.pop);
|
|
537
548
|
var _arrShift = uncurry(Array.prototype.shift);
|
|
538
|
-
var _arrUnshift = uncurry(Array.prototype.unshift);
|
|
539
549
|
var _arrSplice = uncurry(Array.prototype.splice);
|
|
540
550
|
var _arrReverse = uncurry(Array.prototype.reverse);
|
|
541
551
|
|
|
@@ -706,10 +716,8 @@ module.exports = Object.freeze({
|
|
|
706
716
|
min: _mathMin,
|
|
707
717
|
max: _mathMax,
|
|
708
718
|
parseInt: _parseInt,
|
|
709
|
-
push: _arrPush,
|
|
710
719
|
pop: _arrPop,
|
|
711
720
|
shift: _arrShift,
|
|
712
|
-
unshift: _arrUnshift,
|
|
713
721
|
splice: _arrSplice,
|
|
714
722
|
reverse: _arrReverse,
|
|
715
723
|
toUpperCase: _strToUpperCase,
|