@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/guard-crypto.js
CHANGED
|
@@ -55,6 +55,42 @@ var _createPublicKey = nodeCrypto.createPublicKey;
|
|
|
55
55
|
var _createPrivateKey = nodeCrypto.createPrivateKey;
|
|
56
56
|
var _createSecretKey = nodeCrypto.createSecretKey;
|
|
57
57
|
|
|
58
|
+
/** @internal The key agreement and the key generation, captured at load. Read off the module handle
|
|
59
|
+
* at call time, each decides a value no later check recovers: a replaced agreement returns the
|
|
60
|
+
* traditional half of a shared secret outright, measured by driving `pki.hpke.decap` with one
|
|
61
|
+
* returning a fixed buffer, which derived a secret from the value the replacement chose; and a
|
|
62
|
+
* replaced generation decides the ephemeral key an encapsulation is made under. `node:crypto` is an
|
|
63
|
+
* ordinary module object that nothing freezes, so the handle is as replaceable as a prototype. */
|
|
64
|
+
var _diffieHellman = nodeCrypto.diffieHellman;
|
|
65
|
+
var _generateKeyPairSync = nodeCrypto.generateKeyPairSync;
|
|
66
|
+
|
|
67
|
+
/** @internal The ML-KEM encapsulation and decapsulation, and the AEAD transform constructions, all
|
|
68
|
+
* captured at load for the same reason as the agreement above: each returns or decides a value no
|
|
69
|
+
* later check recovers. `encapsulate` and `decapsulate` carry the post-quantum half of a hybrid
|
|
70
|
+
* shared secret, and the two transform constructions decide the cipher a seal and an open run
|
|
71
|
+
* under, so a replacement returns a ciphertext of its own choosing. */
|
|
72
|
+
var _encapsulate = nodeCrypto.encapsulate;
|
|
73
|
+
var _decapsulate = nodeCrypto.decapsulate;
|
|
74
|
+
var _createCipheriv = nodeCrypto.createCipheriv;
|
|
75
|
+
var _createDecipheriv = nodeCrypto.createDecipheriv;
|
|
76
|
+
|
|
77
|
+
/** @internal The randomness, the password-based and extract-and-expand KDFs, the RSA transforms and
|
|
78
|
+
* the ephemeral-agreement constructor, all captured at load for the same reason. Each decides a
|
|
79
|
+
* value outright rather than a claim about one: the randomness is where a content-encryption key, a
|
|
80
|
+
* nonce, an IV and a salt are born, so a replacement returning a value it knows hands it every
|
|
81
|
+
* message those protect; a replaced KDF decides the key-encryption key a password unwraps; and a
|
|
82
|
+
* replaced RSA transform decides the key-transport ciphertext a recipient receives, or the secret a
|
|
83
|
+
* recipient recovers from one. */
|
|
84
|
+
var _randomBytes = nodeCrypto.randomBytes;
|
|
85
|
+
var _randomFillSync = nodeCrypto.randomFillSync;
|
|
86
|
+
var _randomUUID = nodeCrypto.randomUUID;
|
|
87
|
+
var _pbkdf2Sync = nodeCrypto.pbkdf2Sync;
|
|
88
|
+
var _pbkdf2 = nodeCrypto.pbkdf2;
|
|
89
|
+
var _hkdfSync = nodeCrypto.hkdfSync;
|
|
90
|
+
var _publicEncrypt = nodeCrypto.publicEncrypt;
|
|
91
|
+
var _privateDecrypt = nodeCrypto.privateDecrypt;
|
|
92
|
+
var _createECDH = nodeCrypto.createECDH;
|
|
93
|
+
|
|
58
94
|
/** @internal The three KeyObject `export` methods, captured at load. `node:crypto` exports no
|
|
59
95
|
* constructor carrying them: `KeyObject.prototype` has no `export`, and `PublicKeyObject`,
|
|
60
96
|
* `PrivateKeyObject` and `SecretKeyObject` each own one. So one sample pair and one secret key are
|
|
@@ -74,6 +110,68 @@ var _publicExport = intrinsic.uncurry(_publicProto.export);
|
|
|
74
110
|
var _privateExport = intrinsic.uncurry(_privateProto.export);
|
|
75
111
|
var _secretExport = intrinsic.uncurry(_secretProto.export);
|
|
76
112
|
|
|
113
|
+
/** @internal The KeyObject identity accessors, captured at load. These are GETTERS rather than
|
|
114
|
+
* methods, which makes them no less replaceable and the reads no less live: `key.asymmetricKeyType`
|
|
115
|
+
* is a call into a function the prototype holds. What each answers is which key this IS, and that
|
|
116
|
+
* decides an algorithm binding, a curve, a modulus length and whether a pair corresponds, so a
|
|
117
|
+
* replacement answering `"rsa"` for an Ed25519 key made an import accept that key as RSA-PSS, which
|
|
118
|
+
* is a type confusion on the one question the import exists to settle. They sit on the shared
|
|
119
|
+
* parents (`KeyObject.prototype` and the asymmetric parent between it and the two key prototypes),
|
|
120
|
+
* so the descriptors are taken from there rather than from the leaf prototypes. */
|
|
121
|
+
function _getterOf(proto, name) {
|
|
122
|
+
for (var cur = proto; cur !== null && cur !== intrinsic.ObjectProto; cur = intrinsic.getPrototypeOf(cur)) {
|
|
123
|
+
var d = intrinsic.getOwnPropertyDescriptor(cur, name);
|
|
124
|
+
if (d !== undefined && typeof d.get === "function") return intrinsic.uncurry(d.get);
|
|
125
|
+
}
|
|
126
|
+
throw new TypeError("guard-crypto: node:crypto carries no " + name + " accessor to capture");
|
|
127
|
+
}
|
|
128
|
+
var _keyTypeGet = _getterOf(_publicProto, "asymmetricKeyType");
|
|
129
|
+
var _keyDetailsGet = _getterOf(_publicProto, "asymmetricKeyDetails");
|
|
130
|
+
var _keyKindGet = _getterOf(_publicProto, "type");
|
|
131
|
+
var _secretSizeGet = _getterOf(_secretProto, "symmetricKeySize");
|
|
132
|
+
|
|
133
|
+
/** @internal The AEAD transform methods, captured at load off the two prototypes. Capturing the
|
|
134
|
+
* CONSTRUCTION is not enough on its own: the object it returns carries its methods as ordinary
|
|
135
|
+
* prototype properties, so a caller reaching one through that object takes a live read. The
|
|
136
|
+
* authentication tag is the worst of them, because a replaced `setAuthTag` makes a decryptor
|
|
137
|
+
* authenticate against a tag it was never handed, which is a fail-open on the only check that says
|
|
138
|
+
* an AEAD message is genuine, and a replaced `getAuthTag` puts a chosen tag on the wire.
|
|
139
|
+
*
|
|
140
|
+
* `Cipheriv` and `Decipheriv` own SEPARATE copies and carry different sets: only an encryptor has
|
|
141
|
+
* `getAuthTag` and only a decryptor has `setAuthTag`, so the two are captured apart and a verb that
|
|
142
|
+
* belongs to one refuses the other rather than reaching a method that is not there. The sample
|
|
143
|
+
* transforms are discarded; AES-256-GCM is inside the FIPS boundary, so the load stays loadable
|
|
144
|
+
* under `crypto.setFips(1)` for the reason the key pair above gives. */
|
|
145
|
+
var _sampleKey = intrinsic.bufferAlloc(32);
|
|
146
|
+
var _sampleIv = intrinsic.bufferAlloc(12);
|
|
147
|
+
var _cipherProto = intrinsic.getPrototypeOf(_createCipheriv("aes-256-gcm", _sampleKey, _sampleIv));
|
|
148
|
+
var _decipherProto = intrinsic.getPrototypeOf(_createDecipheriv("aes-256-gcm", _sampleKey, _sampleIv));
|
|
149
|
+
var _cipherUpdate = intrinsic.uncurry(_cipherProto.update);
|
|
150
|
+
var _cipherFinal = intrinsic.uncurry(_cipherProto.final);
|
|
151
|
+
var _cipherSetAAD = intrinsic.uncurry(_cipherProto.setAAD);
|
|
152
|
+
var _cipherGetAuthTag = intrinsic.uncurry(_cipherProto.getAuthTag);
|
|
153
|
+
var _cipherSetAutoPadding = intrinsic.uncurry(_cipherProto.setAutoPadding);
|
|
154
|
+
var _decipherUpdate = intrinsic.uncurry(_decipherProto.update);
|
|
155
|
+
var _decipherFinal = intrinsic.uncurry(_decipherProto.final);
|
|
156
|
+
var _decipherSetAAD = intrinsic.uncurry(_decipherProto.setAAD);
|
|
157
|
+
var _decipherSetAuthTag = intrinsic.uncurry(_decipherProto.setAuthTag);
|
|
158
|
+
var _decipherSetAutoPadding = intrinsic.uncurry(_decipherProto.setAutoPadding);
|
|
159
|
+
|
|
160
|
+
/** @internal The ephemeral-agreement methods and the point conversion, captured at load for the same
|
|
161
|
+
* reason. Each decides an EC point, which is a public key: a replacement returns a point of its own
|
|
162
|
+
* choosing, and a caller that pins a key then pins the replacement's. `convertKey` is a static on
|
|
163
|
+
* the constructor rather than a module property, which makes it no less replaceable. */
|
|
164
|
+
var _ecdhProto = intrinsic.getPrototypeOf(_createECDH("prime256v1"));
|
|
165
|
+
var _ecdhSetPrivateKey = intrinsic.uncurry(_ecdhProto.setPrivateKey);
|
|
166
|
+
var _ecdhGetPublicKey = intrinsic.uncurry(_ecdhProto.getPublicKey);
|
|
167
|
+
var _ecdhConvertKey = nodeCrypto.ECDH.convertKey;
|
|
168
|
+
|
|
169
|
+
/** @internal Node's own WebCrypto `exportKey`, with the object it is called on, both captured at
|
|
170
|
+
* load. It is reached as `crypto.webcrypto.subtle.exportKey`, which is three property reads deep,
|
|
171
|
+
* and it returns key material. */
|
|
172
|
+
var _nodeSubtle = nodeCrypto.webcrypto.subtle;
|
|
173
|
+
var _nodeSubtleExportKey = intrinsic.uncurry(_nodeSubtle.exportKey);
|
|
174
|
+
|
|
77
175
|
/** A signature verified through the operation captured at load. Same arguments as `crypto.verify`.
|
|
78
176
|
*
|
|
79
177
|
* `crypto.verify` is an ordinary writable property of the module object, and it was read once per
|
|
@@ -121,8 +219,10 @@ function sign(algorithm, data, key) {
|
|
|
121
219
|
* replaced hash `update` cannot choose the content a message digest covers, driven through
|
|
122
220
|
* `pki.cms.authenticate` and read back with `pki.cms.decrypt`.
|
|
123
221
|
*/
|
|
124
|
-
function digest(name, bytes) {
|
|
125
|
-
|
|
222
|
+
function digest(name, bytes, encodings) {
|
|
223
|
+
var inputEncoding = encodings === undefined ? undefined : encodings.input;
|
|
224
|
+
var outputEncoding = encodings === undefined ? undefined : encodings.output;
|
|
225
|
+
return _hashDigest(_hashUpdate(_createHash(name), bytes, inputEncoding), outputEncoding);
|
|
126
226
|
}
|
|
127
227
|
|
|
128
228
|
/** A digest over SEVERAL parts, fed in order through the operations captured at load. It is `digest`
|
|
@@ -136,12 +236,23 @@ function digest(name, bytes) {
|
|
|
136
236
|
*
|
|
137
237
|
* @enforced-by behavioral -- shares the unarmed shape `digest` below describes.
|
|
138
238
|
*/
|
|
139
|
-
function digestParts(name, parts) {
|
|
140
|
-
var h = _createHash(name);
|
|
239
|
+
function digestParts(name, parts, outLen) {
|
|
240
|
+
var h = outLen === undefined ? _createHash(name) : _createHash(name, { outputLength: outLen });
|
|
141
241
|
for (var i = 0; i < parts.length; i++) _hashUpdate(h, parts[i]);
|
|
142
242
|
return _hashDigest(h);
|
|
143
243
|
}
|
|
144
244
|
|
|
245
|
+
/** A hash handle, through the construction captured at load, for a caller that feeds it in chunks and
|
|
246
|
+
* cannot hold the whole input. An unavailable digest name throws here, which is also how a caller
|
|
247
|
+
* asks whether one is available.
|
|
248
|
+
*
|
|
249
|
+
* @enforced-by guard-shape-reinlined
|
|
250
|
+
* @guard-shape \.createHash\s*\(
|
|
251
|
+
*/
|
|
252
|
+
function hash(name, outLen) {
|
|
253
|
+
return outLen === undefined ? _createHash(name) : _createHash(name, { outputLength: outLen });
|
|
254
|
+
}
|
|
255
|
+
|
|
145
256
|
/** An extendable-output function squeezed to `outLen` bytes, through the operations captured at load.
|
|
146
257
|
* A single-stage KDF derives a key pair and the HPKE key schedule's secrets this way, so a replaced
|
|
147
258
|
* `update` chooses what the derivation covers and a replaced `digest` chooses the key material itself.
|
|
@@ -164,29 +275,398 @@ function xof(name, bytes, outLen) {
|
|
|
164
275
|
* @enforced-by behavioral -- the Hmac prototype's `update` and `digest` are ordinary writable
|
|
165
276
|
* properties, with the same absence of a rename-proof shape as `digest` above. The guard is the RED
|
|
166
277
|
* conformance vector over the key schedule.
|
|
278
|
+
*
|
|
279
|
+
* @enforced-by guard-shape-reinlined
|
|
280
|
+
* @guard-shape \.createHmac\s*\(
|
|
167
281
|
*/
|
|
168
282
|
function hmac(name, key, bytes) {
|
|
169
283
|
return _hmacDigest(_hmacUpdate(_createHmac(name, key), bytes));
|
|
170
284
|
}
|
|
171
285
|
|
|
172
286
|
/** A key imported through the operation captured at load. Same arguments as `crypto.createPublicKey`,
|
|
173
|
-
* `crypto.createPrivateKey` and `crypto.createSecretKey`.
|
|
287
|
+
* `crypto.createPrivateKey` and `crypto.createSecretKey`. A verifier checks a signature against
|
|
288
|
+
* whatever key object it is handed, so an import returning another genuine key of the same family
|
|
289
|
+
* makes a signature made by that key verify against the material a caller pinned.
|
|
174
290
|
*
|
|
175
|
-
* @enforced-by
|
|
176
|
-
*
|
|
177
|
-
* module property directly on the key-agreement, KEM and key-format paths, so arming it now would fail
|
|
178
|
-
* the gate on a clean tree. It arms with that migration. Until then the guard is the RED conformance
|
|
179
|
-
* vector: a replaced `crypto.createPublicKey` returning another genuine key cannot substitute the key a
|
|
180
|
-
* signature is verified against, driven through `pki.tlog.verifyNote` and `pki.key.publicFromPrivate`.
|
|
291
|
+
* @enforced-by guard-shape-reinlined
|
|
292
|
+
* @guard-shape \.createPublicKey\s*\(
|
|
181
293
|
*/
|
|
182
294
|
function publicKey(spec) { return _createPublicKey(spec); }
|
|
183
295
|
|
|
184
|
-
|
|
296
|
+
/** A private key imported through the operation captured at load. The signer's own key is chosen
|
|
297
|
+
* here, so a replacement signs with a key the caller never named.
|
|
298
|
+
*
|
|
299
|
+
* @enforced-by guard-shape-reinlined
|
|
300
|
+
* @guard-shape \.createPrivateKey\s*\(
|
|
301
|
+
*/
|
|
185
302
|
function privateKey(spec) { return _createPrivateKey(spec); }
|
|
186
303
|
|
|
187
|
-
|
|
304
|
+
/** A raw key imported through the operation captured at load. A MAC key substituted at import makes
|
|
305
|
+
* a MAC verify against material the caller never supplied.
|
|
306
|
+
*
|
|
307
|
+
* @enforced-by guard-shape-reinlined
|
|
308
|
+
* @guard-shape \.createSecretKey\s*\(
|
|
309
|
+
*/
|
|
188
310
|
function secretKey(material) { return _createSecretKey(material); }
|
|
189
311
|
|
|
312
|
+
/** The static Diffie-Hellman agreement, through the operation captured at load. `crypto.diffieHellman`
|
|
313
|
+
* read off the module handle at call time returns the traditional half of a shared secret, so a
|
|
314
|
+
* replacement supplies that half outright: driving `pki.hpke.decap` with one returning a fixed buffer
|
|
315
|
+
* derived a secret from the value the replacement chose, and no later check recovers it, because the
|
|
316
|
+
* value IS the secret rather than a claim about it.
|
|
317
|
+
*
|
|
318
|
+
* @enforced-by guard-shape-reinlined
|
|
319
|
+
* @guard-shape (?<!guard\.crypto)\.diffieHellman\s*\(
|
|
320
|
+
*/
|
|
321
|
+
function diffieHellman(spec) { return _diffieHellman(spec); }
|
|
322
|
+
|
|
323
|
+
/** A key pair, through the operation captured at load. A replacement decides the ephemeral key an
|
|
324
|
+
* encapsulation is made under, which is the other half of the same exchange.
|
|
325
|
+
*
|
|
326
|
+
* @enforced-by guard-shape-reinlined
|
|
327
|
+
* @guard-shape \.generateKeyPairSync\s*\(
|
|
328
|
+
*/
|
|
329
|
+
function generateKeyPair(type, options) {
|
|
330
|
+
return options === undefined ? _generateKeyPairSync(type) : _generateKeyPairSync(type, options);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** The ML-KEM encapsulation, through the operation captured at load. It returns the post-quantum half
|
|
334
|
+
* of a hybrid shared secret outright, so a replacement supplies that half.
|
|
335
|
+
*
|
|
336
|
+
* @enforced-by guard-shape-reinlined
|
|
337
|
+
* @guard-shape (?<!guard\.crypto)\.encapsulate\s*\(
|
|
338
|
+
* @guard-via compositeKem\.encapsulate\s*\(
|
|
339
|
+
*/
|
|
340
|
+
function encapsulate(publicKeyObject) { return _encapsulate(publicKeyObject); }
|
|
341
|
+
|
|
342
|
+
/** The ML-KEM decapsulation, through the operation captured at load.
|
|
343
|
+
*
|
|
344
|
+
* @enforced-by guard-shape-reinlined
|
|
345
|
+
* @guard-shape (?<!guard\.crypto)\.decapsulate\s*\(
|
|
346
|
+
* @guard-via compositeKem\.decapsulate\s*\(
|
|
347
|
+
*/
|
|
348
|
+
function decapsulate(privateKeyObject, enc) { return _decapsulate(privateKeyObject, enc); }
|
|
349
|
+
|
|
350
|
+
/** An AEAD encryption transform, through the construction captured at load. A replacement decides the
|
|
351
|
+
* cipher a seal runs under, and therefore the ciphertext and the tag.
|
|
352
|
+
*
|
|
353
|
+
* @enforced-by guard-shape-reinlined
|
|
354
|
+
* @guard-shape \.createCipheriv\s*\(
|
|
355
|
+
*/
|
|
356
|
+
function cipher(algorithm, key, iv, options) {
|
|
357
|
+
return options === undefined ? _createCipheriv(algorithm, key, iv)
|
|
358
|
+
: _createCipheriv(algorithm, key, iv, options);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** An AEAD decryption transform, through the construction captured at load.
|
|
362
|
+
*
|
|
363
|
+
* @enforced-by guard-shape-reinlined
|
|
364
|
+
* @guard-shape \.createDecipheriv\s*\(
|
|
365
|
+
*/
|
|
366
|
+
function decipher(algorithm, key, iv, options) {
|
|
367
|
+
return options === undefined ? _createDecipheriv(algorithm, key, iv)
|
|
368
|
+
: _createDecipheriv(algorithm, key, iv, options);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/** Random octets, through the operation captured at load. This is where a content-encryption key, a
|
|
372
|
+
* MAC key, an IV, a nonce and a salt are born, so a replacement returning a value it already knows
|
|
373
|
+
* hands it every message those protect, and nothing downstream can tell a chosen key from a random
|
|
374
|
+
* one.
|
|
375
|
+
*
|
|
376
|
+
* @enforced-by guard-shape-reinlined
|
|
377
|
+
* @guard-shape (?<!guard\.crypto)\.randomBytes\s*\(
|
|
378
|
+
*/
|
|
379
|
+
function randomBytes(n) { return _randomBytes(n); }
|
|
380
|
+
|
|
381
|
+
/** A buffer filled with random octets in place, through the operation captured at load.
|
|
382
|
+
*
|
|
383
|
+
* @enforced-by guard-shape-reinlined
|
|
384
|
+
* @guard-shape \.randomFillSync\s*\(
|
|
385
|
+
*/
|
|
386
|
+
function randomFill(buffer) { return _randomFillSync(buffer); }
|
|
387
|
+
|
|
388
|
+
/** A random UUID, through the operation captured at load.
|
|
389
|
+
*
|
|
390
|
+
* @enforced-by guard-shape-reinlined
|
|
391
|
+
* @guard-shape (?<!guard\.crypto)\.randomUUID\s*\(
|
|
392
|
+
*/
|
|
393
|
+
function randomUUID() { return _randomUUID(); }
|
|
394
|
+
|
|
395
|
+
/** The PBKDF2 derivation, through the operation captured at load. It decides the key-encryption key a
|
|
396
|
+
* password unwraps, so a replacement returning a fixed value makes every password open the message.
|
|
397
|
+
*
|
|
398
|
+
* @enforced-by guard-shape-reinlined
|
|
399
|
+
* @guard-shape \.pbkdf2Sync\s*\(
|
|
400
|
+
*/
|
|
401
|
+
function pbkdf2(password, salt, iterations, keylen, digestName) {
|
|
402
|
+
return _pbkdf2Sync(password, salt, iterations, keylen, digestName);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/** The PBKDF2 derivation in its callback form, through the operation captured at load.
|
|
406
|
+
*
|
|
407
|
+
* @enforced-by guard-shape-reinlined
|
|
408
|
+
* @guard-shape (?<!guard\.crypto)\.pbkdf2\s*\(
|
|
409
|
+
*/
|
|
410
|
+
function pbkdf2Async(password, salt, iterations, keylen, digestName, callback) {
|
|
411
|
+
return _pbkdf2(password, salt, iterations, keylen, digestName, callback);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** The HKDF expand-and-extract, through the operation captured at load.
|
|
415
|
+
*
|
|
416
|
+
* @enforced-by guard-shape-reinlined
|
|
417
|
+
* @guard-shape \.hkdfSync\s*\(
|
|
418
|
+
*/
|
|
419
|
+
function hkdf(digestName, ikm, salt, info, keylen) {
|
|
420
|
+
return _hkdfSync(digestName, ikm, salt, info, keylen);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/** The RSA public-key transform, through the operation captured at load. It decides the key-transport
|
|
424
|
+
* ciphertext a recipient receives, so a replacement encrypts to a key of its own choosing.
|
|
425
|
+
*
|
|
426
|
+
* @enforced-by guard-shape-reinlined
|
|
427
|
+
* @guard-shape (?<!guard\.crypto)\.publicEncrypt\s*\(
|
|
428
|
+
*/
|
|
429
|
+
function publicEncrypt(spec, bytes) { return _publicEncrypt(spec, bytes); }
|
|
430
|
+
|
|
431
|
+
/** The RSA private-key transform, through the operation captured at load. It returns the secret a
|
|
432
|
+
* recipient recovers from a key-transport ciphertext, so a replacement supplies that secret.
|
|
433
|
+
*
|
|
434
|
+
* @enforced-by guard-shape-reinlined
|
|
435
|
+
* @guard-shape (?<!guard\.crypto)\.privateDecrypt\s*\(
|
|
436
|
+
*/
|
|
437
|
+
function privateDecrypt(spec, bytes) { return _privateDecrypt(spec, bytes); }
|
|
438
|
+
|
|
439
|
+
/** An ephemeral elliptic-curve agreement, through the constructor captured at load. The object it
|
|
440
|
+
* returns carries its methods live, so a caller derives a point with `ecPointFromScalar` rather than
|
|
441
|
+
* driving this one.
|
|
442
|
+
*
|
|
443
|
+
* @enforced-by guard-shape-reinlined
|
|
444
|
+
* @guard-shape \.createECDH\s*\(
|
|
445
|
+
*/
|
|
446
|
+
function ecdh(curveName) { return _createECDH(curveName); }
|
|
447
|
+
|
|
448
|
+
/** The EC point a scalar generates, in uncompressed SEC1 form, with the agreement built and driven
|
|
449
|
+
* entirely through operations captured at load. A point is a public key, so a replaced
|
|
450
|
+
* `setPrivateKey` or `getPublicKey` returns one of its own choosing and a caller that pins a key
|
|
451
|
+
* pins the replacement's.
|
|
452
|
+
*
|
|
453
|
+
* @enforced-by guard-shape-reinlined
|
|
454
|
+
* @guard-shape \.setPrivateKey\s*\(
|
|
455
|
+
*/
|
|
456
|
+
function ecPointFromScalar(curveName, scalar) {
|
|
457
|
+
var handle = _createECDH(curveName);
|
|
458
|
+
_ecdhSetPrivateKey(handle, scalar);
|
|
459
|
+
return _ecdhGetPublicKey(handle, null, "uncompressed");
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/** An EC point converted between SEC1 forms, through the static captured at load. De-compressing a
|
|
463
|
+
* point is also what decides it is ON the curve, so a replacement answers both questions.
|
|
464
|
+
*
|
|
465
|
+
* @enforced-by guard-shape-reinlined
|
|
466
|
+
* @guard-shape \.convertKey\s*\(
|
|
467
|
+
*/
|
|
468
|
+
function ecConvertPoint(point, curveName, format) {
|
|
469
|
+
return _ecdhConvertKey(point, curveName, undefined, undefined, format);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/** Key material exported through NODE's own WebCrypto, reached through the operation and the receiver
|
|
473
|
+
* captured at load. This is the fallback for a `CryptoKey` from another implementation, and it
|
|
474
|
+
* returns key material, so a replacement decides those bytes.
|
|
475
|
+
*
|
|
476
|
+
* @enforced-by guard-shape-reinlined
|
|
477
|
+
* @guard-shape \.webcrypto\.subtle\.exportKey\s*\(
|
|
478
|
+
*/
|
|
479
|
+
function nodeExportKey(format, key) { return _nodeSubtleExportKey(_nodeSubtle, format, key); }
|
|
480
|
+
|
|
481
|
+
/** @internal Which of the two transform prototypes `t` has. A verb that belongs to one direction
|
|
482
|
+
* refuses the other rather than reaching for a method that is not there, and the question is asked
|
|
483
|
+
* of the PROTOTYPE rather than with `instanceof`, which consults a `Symbol.hasInstance` the
|
|
484
|
+
* constructor's holder can replace. */
|
|
485
|
+
function _transformKind(t) {
|
|
486
|
+
var proto = t === null || t === undefined ? null : intrinsic.getPrototypeOf(t);
|
|
487
|
+
if (proto === _cipherProto) return "cipher";
|
|
488
|
+
if (proto === _decipherProto) return "decipher";
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/** Bytes put through an AEAD or block transform, in either direction, through the method captured at
|
|
493
|
+
* load for that direction.
|
|
494
|
+
*
|
|
495
|
+
* @enforced-by behavioral -- the shape it would declare is the one `guard.secret.cipherFinish`
|
|
496
|
+
* already owns (an `update` paired with a `final`), and that guard is the only caller: a transform is
|
|
497
|
+
* driven to produce bytes that owe a wipe, so the two rules live at one door.
|
|
498
|
+
*/
|
|
499
|
+
function transformUpdate(t, bytes) {
|
|
500
|
+
var kind = _transformKind(t);
|
|
501
|
+
if (kind === "cipher") return _cipherUpdate(t, bytes);
|
|
502
|
+
if (kind === "decipher") return _decipherUpdate(t, bytes);
|
|
503
|
+
throw new TypeError("guard.crypto.transformUpdate: expects a node:crypto cipher or decipher");
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** The trailing bytes of a transform, through the method captured at load for its direction.
|
|
507
|
+
*
|
|
508
|
+
* @enforced-by behavioral -- shares the note on `transformUpdate` above, whose pair it is.
|
|
509
|
+
*/
|
|
510
|
+
function transformFinal(t) {
|
|
511
|
+
var kind = _transformKind(t);
|
|
512
|
+
if (kind === "cipher") return _cipherFinal(t);
|
|
513
|
+
if (kind === "decipher") return _decipherFinal(t);
|
|
514
|
+
throw new TypeError("guard.crypto.transformFinal: expects a node:crypto cipher or decipher");
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/** The additional authenticated data an AEAD transform covers, in either direction. A replacement
|
|
518
|
+
* changes what the tag commits to without changing the tag.
|
|
519
|
+
*
|
|
520
|
+
* @enforced-by guard-shape-reinlined
|
|
521
|
+
* @guard-shape (?<!guard\.crypto)\.setAAD\s*\(
|
|
522
|
+
*/
|
|
523
|
+
function transformSetAAD(t, aad) {
|
|
524
|
+
var kind = _transformKind(t);
|
|
525
|
+
if (kind === "cipher") return _cipherSetAAD(t, aad);
|
|
526
|
+
if (kind === "decipher") return _decipherSetAAD(t, aad);
|
|
527
|
+
throw new TypeError("guard.crypto.transformSetAAD: expects a node:crypto cipher or decipher");
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/** Turns a transform's automatic padding off, in either direction. The key-wrap and CBC paths need
|
|
531
|
+
* the block boundary they computed, not one the transform adds, so a replacement that leaves padding
|
|
532
|
+
* on changes the block count a wrap produces.
|
|
533
|
+
*
|
|
534
|
+
* @enforced-by guard-shape-reinlined
|
|
535
|
+
* @guard-shape (?<!guard\.crypto)\.setAutoPadding\s*\(
|
|
536
|
+
*/
|
|
537
|
+
function transformNoPadding(t) {
|
|
538
|
+
var kind = _transformKind(t);
|
|
539
|
+
if (kind === "cipher") return _cipherSetAutoPadding(t, false);
|
|
540
|
+
if (kind === "decipher") return _decipherSetAutoPadding(t, false);
|
|
541
|
+
throw new TypeError("guard.crypto.transformNoPadding: expects a node:crypto cipher or decipher");
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** The authentication tag an encryptor produced. Only an encryptor carries it, so a decryptor is
|
|
545
|
+
* refused rather than silently answering undefined, and a replacement puts a chosen tag on the wire.
|
|
546
|
+
*
|
|
547
|
+
* @enforced-by guard-shape-reinlined
|
|
548
|
+
* @guard-shape (?<!guard\.crypto)\.getAuthTag\s*\(
|
|
549
|
+
*/
|
|
550
|
+
function cipherAuthTag(t) {
|
|
551
|
+
if (_transformKind(t) !== "cipher") {
|
|
552
|
+
throw new TypeError("guard.crypto.cipherAuthTag: expects a node:crypto cipher");
|
|
553
|
+
}
|
|
554
|
+
return _cipherGetAuthTag(t);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** The authentication tag a decryptor must verify against. Only a decryptor carries it. This is the
|
|
558
|
+
* single check that says an AEAD message is genuine, so a replacement that discards the tag makes the
|
|
559
|
+
* decryptor authenticate against one it was never handed, and the message opens.
|
|
560
|
+
*
|
|
561
|
+
* @enforced-by guard-shape-reinlined
|
|
562
|
+
* @guard-shape (?<!guard\.crypto)\.setAuthTag\s*\(
|
|
563
|
+
*/
|
|
564
|
+
function decipherSetAuthTag(t, tag) {
|
|
565
|
+
if (_transformKind(t) !== "decipher") {
|
|
566
|
+
throw new TypeError("guard.crypto.decipherSetAuthTag: expects a node:crypto decipher");
|
|
567
|
+
}
|
|
568
|
+
return _decipherSetAuthTag(t, tag);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/** @internal Whether `v` is a public or a private KeyObject, which are the two the asymmetric
|
|
572
|
+
* accessors belong to. A SECRET KeyObject is a KeyObject and is not one of them: node refuses the
|
|
573
|
+
* accessor outright for that receiver, so a verb that admitted all three and then reached for it
|
|
574
|
+
* turned a caller's wrong key kind into a raw TypeError where its module had promised a typed
|
|
575
|
+
* refusal. The tolerant verbs below ask this rather than `isKeyObject`. */
|
|
576
|
+
function _isAsymmetricKeyObject(v) {
|
|
577
|
+
var proto = v === null || v === undefined ? null : intrinsic.getPrototypeOf(v);
|
|
578
|
+
return proto === _publicProto || proto === _privateProto;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/** The algorithm family of `v` when `v` is an asymmetric KeyObject, and `undefined` for anything
|
|
582
|
+
* else, a secret key included. The call sites that ask this are deciding whether a caller handed them
|
|
583
|
+
* an asymmetric key at all, and the duck-typed form they asked it with (`typeof v === "object" &&
|
|
584
|
+
* v.asymmetricKeyType != null`) is satisfied by a plain object carrying that one field, so a forged
|
|
585
|
+
* object passed as a key and was then used as one. Asking the prototype first settles both questions
|
|
586
|
+
* at once, and a secret key answers `undefined` here exactly as the accessor itself did.
|
|
587
|
+
*
|
|
588
|
+
* @enforced-by behavioral -- the shape is `keyType`'s, which is declared on it below; this is the
|
|
589
|
+
* tolerant door onto the same accessor, and the RED conformance vector drives a forged object and a
|
|
590
|
+
* secret key through the verbs that used to accept them.
|
|
591
|
+
*/
|
|
592
|
+
function keyTypeOf(v) { return _isAsymmetricKeyObject(v) ? _keyTypeGet(v) : undefined; }
|
|
593
|
+
|
|
594
|
+
/** Whether `v` is "public", "private" or "secret" when it IS a KeyObject, and `undefined` otherwise.
|
|
595
|
+
*
|
|
596
|
+
* @enforced-by behavioral -- shares the note on `keyTypeOf` above.
|
|
597
|
+
*/
|
|
598
|
+
function keyKindOf(v) { return isKeyObject(v) ? _keyKindGet(v) : undefined; }
|
|
599
|
+
|
|
600
|
+
/** A key's algorithm parameters when `v` is an asymmetric KeyObject, and `undefined` for anything
|
|
601
|
+
* else, a secret key included.
|
|
602
|
+
*
|
|
603
|
+
* @enforced-by behavioral -- shares the note on `keyTypeOf` above.
|
|
604
|
+
*/
|
|
605
|
+
function keyDetailsOf(v) { return _isAsymmetricKeyObject(v) ? _keyDetailsGet(v) : undefined; }
|
|
606
|
+
|
|
607
|
+
/** Which algorithm family a key belongs to ("ed25519", "rsa", "rsa-pss", "ec", "x25519", ...), read
|
|
608
|
+
* through the accessor captured at load. This is the one question an import exists to settle, and it
|
|
609
|
+
* decides which algorithm a signature is checked under, so a replacement answering `"rsa"` for an
|
|
610
|
+
* Ed25519 key made an import accept it as RSA-PSS.
|
|
611
|
+
*
|
|
612
|
+
* @enforced-by guard-shape-reinlined
|
|
613
|
+
* @guard-shape (?<!guard\.crypto)\.asymmetricKeyType\b
|
|
614
|
+
*/
|
|
615
|
+
function keyType(keyObject) {
|
|
616
|
+
if (!_isAsymmetricKeyObject(keyObject)) {
|
|
617
|
+
throw new TypeError("guard.crypto.keyType: expects a node:crypto public or private KeyObject");
|
|
618
|
+
}
|
|
619
|
+
return _keyTypeGet(keyObject);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/** A key's algorithm parameters (`modulusLength`, `namedCurve`, `hashAlgorithm`, ...), read through
|
|
623
|
+
* the accessor captured at load. A modulus length and a curve name are both checks a caller pinned.
|
|
624
|
+
*
|
|
625
|
+
* @enforced-by guard-shape-reinlined
|
|
626
|
+
* @guard-shape (?<!guard\.crypto)\.asymmetricKeyDetails\b
|
|
627
|
+
*/
|
|
628
|
+
function keyDetails(keyObject) {
|
|
629
|
+
if (!_isAsymmetricKeyObject(keyObject)) {
|
|
630
|
+
throw new TypeError("guard.crypto.keyDetails: expects a node:crypto public or private KeyObject");
|
|
631
|
+
}
|
|
632
|
+
return _keyDetailsGet(keyObject);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/** Whether a key is "public", "private" or "secret", read through the accessor captured at load. A
|
|
636
|
+
* signer that accepts a public key where it needed a private one, or the reverse, is deciding on this.
|
|
637
|
+
*
|
|
638
|
+
* @enforced-by behavioral -- `.type` is the most common field name in the toolkit, carried by every
|
|
639
|
+
* parsed ASN.1 node and every algorithm descriptor, so a shape matching it would fire on hundreds of
|
|
640
|
+
* sites that are not key objects at all. The guard is the RED conformance vector over the import.
|
|
641
|
+
*/
|
|
642
|
+
function keyKind(keyObject) { return _keyKindGet(keyObject); }
|
|
643
|
+
|
|
644
|
+
/** A raw key's length in bits, read through the accessor captured at load.
|
|
645
|
+
*
|
|
646
|
+
* @enforced-by guard-shape-reinlined
|
|
647
|
+
* @guard-shape (?<!guard\.crypto)\.symmetricKeySize\b
|
|
648
|
+
*/
|
|
649
|
+
function secretKeySize(keyObject) {
|
|
650
|
+
var proto = keyObject === null || keyObject === undefined ? null : intrinsic.getPrototypeOf(keyObject);
|
|
651
|
+
if (proto !== _secretProto) {
|
|
652
|
+
throw new TypeError("guard.crypto.secretKeySize: expects a node:crypto secret KeyObject");
|
|
653
|
+
}
|
|
654
|
+
return _secretSizeGet(keyObject);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/** Whether `v` is one of node's three KeyObject kinds, asked of its PROTOTYPE. `v instanceof
|
|
658
|
+
* crypto.KeyObject` reads the constructor off the module object and then consults a
|
|
659
|
+
* `Symbol.hasInstance` either side can replace, so the answer is taken from the prototypes this
|
|
660
|
+
* module captured at load instead.
|
|
661
|
+
*
|
|
662
|
+
* @enforced-by guard-shape-reinlined
|
|
663
|
+
* @guard-shape instanceof\s+(?:nodeCrypto|crypto)\.KeyObject
|
|
664
|
+
*/
|
|
665
|
+
function isKeyObject(v) {
|
|
666
|
+
var proto = v === null || v === undefined ? null : intrinsic.getPrototypeOf(v);
|
|
667
|
+
return proto === _publicProto || proto === _privateProto || proto === _secretProto;
|
|
668
|
+
}
|
|
669
|
+
|
|
190
670
|
/** A KeyObject exported through the operation captured at load. `keyObject.export(spec)` reaches the
|
|
191
671
|
* method off the live prototype, so a replacement decides the bytes a caller is handed: one exporting
|
|
192
672
|
* a fixed value made two distinct authorized TUF keys carry the same material identifier, which took a
|
|
@@ -224,7 +704,19 @@ function assertOctetAligned(bitString, E, code, label) {
|
|
|
224
704
|
}
|
|
225
705
|
|
|
226
706
|
module.exports = _freeze({ constantTimeEqual: constantTimeEqual, digest: digest,
|
|
227
|
-
digestParts: digestParts, xof: xof, hmac: hmac, verify: verify, sign: sign,
|
|
707
|
+
digestParts: digestParts, xof: xof, hash: hash, hmac: hmac, verify: verify, sign: sign,
|
|
228
708
|
publicKey: publicKey, privateKey: privateKey, secretKey: secretKey, exportKey: exportKey,
|
|
709
|
+
diffieHellman: diffieHellman, generateKeyPair: generateKeyPair,
|
|
710
|
+
encapsulate: encapsulate, decapsulate: decapsulate, cipher: cipher, decipher: decipher,
|
|
711
|
+
randomBytes: randomBytes, randomFill: randomFill, randomUUID: randomUUID,
|
|
712
|
+
pbkdf2: pbkdf2, pbkdf2Async: pbkdf2Async, hkdf: hkdf,
|
|
713
|
+
publicEncrypt: publicEncrypt, privateDecrypt: privateDecrypt,
|
|
714
|
+
ecdh: ecdh, ecPointFromScalar: ecPointFromScalar,
|
|
715
|
+
ecConvertPoint: ecConvertPoint, nodeExportKey: nodeExportKey, isKeyObject: isKeyObject,
|
|
716
|
+
keyType: keyType, keyDetails: keyDetails, keyKind: keyKind, secretKeySize: secretKeySize,
|
|
717
|
+
keyTypeOf: keyTypeOf, keyKindOf: keyKindOf, keyDetailsOf: keyDetailsOf,
|
|
718
|
+
transformUpdate: transformUpdate, transformFinal: transformFinal,
|
|
719
|
+
transformSetAAD: transformSetAAD, transformNoPadding: transformNoPadding,
|
|
720
|
+
cipherAuthTag: cipherAuthTag, decipherSetAuthTag: decipherSetAuthTag,
|
|
229
721
|
padding: padding, saltLength: saltLength,
|
|
230
722
|
isOctetAligned: isOctetAligned, assertOctetAligned: assertOctetAligned });
|
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-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,
|