@blamejs/pki 0.8.60 → 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 CHANGED
@@ -4,6 +4,30 @@ All notable changes to `@blamejs/pki` are documented here. The format
4
4
  follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this
5
5
  project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## v0.8.61 — 2026-10-07
8
+
9
+ Take every cryptographic operation, and every question about which key a key is, through an operation captured when the toolkit loads, so a replacement installed afterwards cannot decide a secret, a tag, a key type or a verdict.
10
+
11
+ ### Added
12
+
13
+ - The internal crypto guard gained the operations the library needed to stop reading `node:crypto` at call time: randomness, the password-based and extract-and-expand derivations, the RSA transforms, the elliptic-curve point derivation and conversion, the AEAD transform methods, the hash handle for a caller that cannot hold its whole input, and the four key-identity accessors. The digest primitive takes input and output encodings. None of this is on the public surface.
14
+
15
+ ### Changed
16
+
17
+ - `pki.webcrypto.subtle.exportKey` and `pki.key.export` read a key's type at most twice per call, once to admit the key and once for every decision that follows. Nothing in the public surface changed shape, and no error code was added or removed.
18
+
19
+ ### Fixed
20
+
21
+ - An imported key is bound to the algorithm the caller named it under. `pki.webcrypto.subtle.importKey` settles that by asking the key which algorithm family it belongs to, and that answer came from an accessor on a node prototype, read at the moment of the check. An accessor answering `rsa` for an Ed25519 key therefore made the import accept it as RSA-PSS, and every later operation ran under an algorithm the key does not belong to. The accessor is captured when the engine loads. The same read also decided a curve, a modulus length and whether a key pair corresponds, across `pki.key`, `pki.tuf`, `pki.tlog`, `pki.sigstore`, `pki.cmc`, `pki.crmf`, `pki.ct` and the signature-scheme check that matches a signer to a certificate.
22
+ - A plain object carrying an `asymmetricKeyType` field is no longer accepted as a key. The sites that asked whether a caller had handed them a key object tested for that one field, which any object can carry, so a forged object passed the test and was then used as a key. The question is asked of the object's prototype now, and the answer settles both whether it is a key and which kind.
23
+ - A shared secret is derived through the agreement the toolkit captured, not one replaced afterwards. `crypto.diffieHellman` returns the traditional half of a hybrid secret outright, so a replacement supplies that half: driving `pki.hpke.decap` with one returning a fixed buffer derived a secret from the value the replacement chose. The post-quantum half, through `encapsulate` and `decapsulate`, had the same shape, as did the key generation that decides the ephemeral key an encapsulation is made under. `pki.hpke`, `pki.kem`, `pki.key`, `pki.cms` and `pki.webcrypto` all take these through operations captured at load.
24
+ - A content-encryption key, a MAC key, an IV, a nonce and a salt are drawn through the randomness the toolkit captured. Twenty-seven sites read it off the module handle when they needed it, so a replacement returning a value it already knows handed it every message those protect, and nothing downstream can tell a chosen key from a random one.
25
+ - An AEAD message is authenticated against the tag it carries. The tag is set and read through methods on the cipher object, which were reached through that object: a replacement decides which tag a ciphertext is checked against, so the verdict stops being a function of the message. The additional authenticated data, the padding mode, and the bytes a transform produces are reached the same way and are now taken through operations captured at load. The streaming paths in `pki.webcrypto` already did this; the one-shot encrypt and decrypt did not.
26
+ - A key-transport ciphertext is produced, and the secret inside one recovered, through the RSA transforms captured at load. A password-derived key-encryption key, an HKDF expansion, and the elliptic-curve point a scalar generates are the same shape: each returns a value rather than a claim about one, so a replacement returning a fixed value makes every password open the message or puts a point of its own choosing where a public key was expected.
27
+ - `pki.key.export` emits a PEM label that agrees with the bytes in the block. It asked the key its type once to choose the label and again to choose the encoding, and on a `CryptoKey` from node's own WebCrypto that is an accessor, so an accessor answering differently across those reads picked the two separately and a public key came back inside a `PRIVATE KEY` block. The type is read once and every decision in an export comes from that one answer.
28
+ - A digest is computed through the hash operation the toolkit captured, across every path that takes one: the certificate and CRL digests, the CMS message digests and countersignature imprints, the transparency-log identifiers, the PKCS#12 key derivation, the hash-based signature trees, the WebAuthn attestation comparisons and the HTTP Digest credential. `pki.scep`'s check that a named digest is available goes through the same operation, so the name it accepts is the name it would use.
29
+ - The RFC 7616 HTTP Digest credential is computed over the octets of the latin1 encoding the specification names, through one operation rather than a copy of the hash construction kept in the module. Three modules held their own copy of what the digest primitive already does; all three route through it now, and the input and output encodings are named at the call rather than defaulted.
30
+
7
31
  ## v0.8.60 — 2026-10-07
8
32
 
9
33
  Build every list a parse or an encode reads from by defining its indexes, so an accessor inherited from the array prototype cannot take an element as it is added.
package/lib/cmc-build.js CHANGED
@@ -470,8 +470,8 @@ function identityProofV2(secret, reqSequenceBytes, identity) {
470
470
  _ownSecret(Buffer.from(identity, "utf8"), owned),
471
471
  ]), owned);
472
472
  }
473
- key = nodeCrypto.createHash("sha256").update(material).digest();
474
- var witness = nodeCrypto.createHmac("sha256", key).update(reqSequenceBytes).digest();
473
+ key = guard.crypto.digest("sha256", material);
474
+ var witness = guard.crypto.hmac("sha256", key, reqSequenceBytes);
475
475
  return b.sequence([algId(OID_SHA256), algId(OID_HMAC_SHA256), b.octetString(witness)]);
476
476
  } finally {
477
477
  if (key) guard.secret.zeroize(key, CmcError, "cmc/bad-input", "the Identity Proof MAC key");
@@ -541,7 +541,7 @@ function _provesRequestKey(opening, outgoing) {
541
541
  /** @internal Keys of different types are never the same key, and comparing them through the
542
542
  * runtime's equality leaves a fault queued in the crypto library that surfaces on the next
543
543
  * unrelated key import in the process, so the type decides that case first. */
544
- if (requested.asymmetricKeyType !== opening.key.asymmetricKeyType) return false;
544
+ if (guard.crypto.keyType(requested) !== guard.crypto.keyType(opening.key)) return false;
545
545
  return intrinsic.keyEquals(requested, opening.key);
546
546
  }
547
547
  /** @internal A key the runtime engine cannot read has no KeyObject to compare, and a composite
@@ -607,7 +607,7 @@ async function _recoverProofValue(decoded, recipient, witnessHash) {
607
607
  continue; // allow:swallow-unverified this recipient is not addressed to the supplied key; the witness decides
608
608
  }
609
609
  var candidate = opened.content;
610
- var computed = nodeCrypto.createHash(witnessHash).update(candidate).digest();
610
+ var computed = guard.crypto.digest(witnessHash, candidate);
611
611
  var matches = computed.length === decoded.witness.length &&
612
612
  guard.crypto.constantTimeEqual(computed, decoded.witness);
613
613
  guard.secret.zeroize(computed, CmcError, "cmc/bad-input", "the computed witness");
@@ -674,7 +674,7 @@ async function answerPopChallenge(popChallenge, ids) {
674
674
  * in the challenge at all: neither side re-encodes it. */
675
675
  macKey = _bufferFrom(proofValue.length > POP_MAC_KEY_MAX_BYTES
676
676
  ? _subarray(proofValue, 0, POP_MAC_KEY_MAX_BYTES) : proofValue);
677
- var thePOP = nodeCrypto.createHmac(macHash, macKey).update(decoded.requestBytes).digest();
677
+ var thePOP = guard.crypto.hmac(macHash, macKey, decoded.requestBytes);
678
678
  return { algBytes: decoded.thePOPAlgID.bytes, thePOP: thePOP, ids: ids,
679
679
  recipientSpki: await _openingPublicKey(recipient, recovered.recipientType),
680
680
  challengedRequest: _requestIdentity(decoded.request) };
@@ -688,13 +688,18 @@ async function answerPopChallenge(popChallenge, ids) {
688
688
 
689
689
  function popLinkWitnessV2(secret, R) {
690
690
  _assertSecret(secret, "a POP Link Witness V2 control");
691
- var key = nodeCrypto.createHash("sha256").update(secret, "utf8").digest();
691
+ /** @internal The secret's octets, held so the finally can wipe them. Handing the string and an
692
+ * encoding to a digest instead leaves the copy inside the provider, where nothing clears it. */
693
+ var material = _bufferFrom(secret, "utf8");
694
+ var key = null;
692
695
  try {
696
+ key = guard.crypto.digest("sha256", material);
693
697
  /** @internal Inside the try, so a MAC that faults on its message still wipes the key above it. */
694
- var witness = nodeCrypto.createHmac("sha256", key).update(R).digest();
698
+ var witness = guard.crypto.hmac("sha256", key, R);
695
699
  return b.sequence([algId(OID_SHA256), algId(OID_HMAC_SHA256), b.octetString(witness)]);
696
700
  } finally {
697
- guard.secret.zeroize(key, CmcError, "cmc/bad-input", "the POP Link MAC key");
701
+ guard.secret.zeroize(material, CmcError, "cmc/bad-input", "the POP Link secret");
702
+ if (key !== null) guard.secret.zeroize(key, CmcError, "cmc/bad-input", "the POP Link MAC key");
698
703
  }
699
704
  }
700
705
 
@@ -935,7 +940,7 @@ async function _build(spec, signer, opts) {
935
940
  if (typeof rBytes !== "number" || !Number.isInteger(rBytes) || rBytes < 1) {
936
941
  throw E("cmc/bad-input", "popLinkRandomBytes must be a positive integer");
937
942
  }
938
- var R = nodeCrypto.randomBytes(rBytes);
943
+ var R = guard.crypto.randomBytes(rBytes);
939
944
  _push(controls,encodeControl(OID_POP_LINK_RANDOM, [b.octetString(R)], ids));
940
945
  _push(controls,encodeControl(O("id-cmc-popLinkWitnessV2"),
941
946
  [popLinkWitnessV2(spec.popLink.secret, R)], ids));
@@ -4,7 +4,6 @@
4
4
  // @internal
5
5
  // @primitive pki.cms.decrypt block live in cms-verify.js, which re-exports this function.
6
6
 
7
- var nodeCrypto = require("crypto");
8
7
  var asn1 = require("./asn1-der");
9
8
  var oid = require("./oid");
10
9
  var x509 = require("./schema-x509");
@@ -235,8 +234,8 @@ async function _ktriCek(ri, km) {
235
234
  return Buffer.from(await subtle.decrypt({ name: "RSA-OAEP" }, pub, ri.encryptedKey));
236
235
  }
237
236
  if (kea.oid === O("rsaEncryption")) {
238
- var keyObj = nodeCrypto.createPrivateKey({ key: k.der, format: "der", type: "pkcs8" });
239
- try { return nodeCrypto.privateDecrypt({ key: keyObj, padding: guard.crypto.padding.RSA_PKCS1 }, ri.encryptedKey); }
237
+ var keyObj = guard.crypto.privateKey({ key: k.der, format: "der", type: "pkcs8" });
238
+ try { return guard.crypto.privateDecrypt({ key: keyObj, padding: guard.crypto.padding.RSA_PKCS1 }, ri.encryptedKey); }
240
239
  catch (_e) {
241
240
  return null;
242
241
  }
@@ -339,7 +338,7 @@ async function _pwriCek(ri, km, opts) {
339
338
  var iv = asn1.read.octetString(inner.children[1]);
340
339
  var pw = pbes2.passwordBytesOwned(km.password, _err, "cms");
341
340
  var kek;
342
- try { kek = nodeCrypto.pbkdf2Sync(pw.bytes, pb.salt, pb.iterations, innerBits / 8, pb.prfNode); }
341
+ try { kek = guard.crypto.pbkdf2(pw.bytes, pb.salt, pb.iterations, innerBits / 8, pb.prfNode); }
343
342
  finally { if (pw.owned) guard.secret.zeroize(pw.bytes, CmsError, "cms/bad-input", "the password encoding"); }
344
343
  try {
345
344
  return _pwriUnwrap(kek, ri.encryptedKey, iv, innerBits);
@@ -421,7 +420,7 @@ async function _openContent(parsed, eci, cek, ct, streamMode) {
421
420
  }
422
421
  if (eci.encryptedContent == null) throw _err("cms/no-encrypted-content", "the message has no encryptedContent (detached; supply it out of band)");
423
422
  var substitute = null;
424
- if (cek == null || cek.length !== keyBits / 8) { substitute = nodeCrypto.randomBytes(keyBits / 8); cek = substitute; }
423
+ if (cek == null || cek.length !== keyBits / 8) { substitute = guard.crypto.randomBytes(keyBits / 8); cek = substitute; }
425
424
  try {
426
425
  if (ct === "authEnvelopedData") {
427
426
  var aad = parsed.authAttrsBytes != null ? _explicitSetOf(parsed.authAttrsBytes) : Buffer.alloc(0);
@@ -461,9 +460,9 @@ async function _openContent(parsed, eci, cek, ct, streamMode) {
461
460
  }
462
461
  function _gcmOpen(cek, nonce, ct, tag, aad, keyBits, icvLen) {
463
462
  if (!tag || tag.length !== icvLen) throw _fail();
464
- var d = nodeCrypto.createDecipheriv("aes-" + keyBits + "-gcm", cek, nonce, { authTagLength: icvLen });
465
- d.setAuthTag(tag);
466
- if (aad && aad.length) d.setAAD(aad);
463
+ var d = guard.crypto.decipher("aes-" + keyBits + "-gcm", cek, nonce, { authTagLength: icvLen });
464
+ guard.crypto.decipherSetAuthTag(d, tag);
465
+ if (aad && aad.length) guard.crypto.transformSetAAD(d, aad);
467
466
  return guard.secret.cipherFinish(d, ct, CmsError, "cms/decrypt-failed", "the recovered content");
468
467
  }
469
468
 
@@ -543,7 +542,7 @@ async function _decryptPbes2(parsed, eci, km, opts) {
543
542
  if (!keyBits) throw _err("cms/unsupported-algorithm", "unsupported PBES2 content cipher " + encOid);
544
543
  var pwE = pbes2.passwordBytesOwned(km.password, _err, "cms");
545
544
  var key;
546
- try { key = nodeCrypto.pbkdf2Sync(pwE.bytes, pb.salt, pb.iterations, keyBits / 8, pb.prfNode); }
545
+ try { key = guard.crypto.pbkdf2(pwE.bytes, pb.salt, pb.iterations, keyBits / 8, pb.prfNode); }
547
546
  finally { if (pwE.owned) guard.secret.zeroize(pwE.bytes, CmsError, "cms/bad-input", "the password encoding"); }
548
547
  try { return _originFields({ content: opts.stream === true ? _cbcStream(key, iv, eci.encryptedContent, keyBits) : pbes2.cbcDecrypt(key, iv, eci.encryptedContent, keyBits, CmsError, "cms/decrypt-failed"), contentType: eci.contentType, contentTypeName: oid.name(eci.contentType) || eci.contentType, recipientType: "password", recipientIndex: -1, contentEncryptionAlgorithm: oid.name(encOid) || encOid, authenticated: false }, null, null); }
549
548
  catch (_e) { throw _fail(); }
@@ -588,13 +587,13 @@ function _pwriUnwrap(kek, wrapped, iv, keyBits) {
588
587
  var n = wrapped.length;
589
588
  var lastDec = null, pass1 = null, body = null;
590
589
  try {
591
- var ecb = nodeCrypto.createDecipheriv("aes-" + keyBits + "-ecb", kek, Buffer.alloc(0)); ecb.setAutoPadding(false);
590
+ var ecb = guard.crypto.decipher("aes-" + keyBits + "-ecb", kek, Buffer.alloc(0)); guard.crypto.transformNoPadding(ecb);
592
591
  lastDec = guard.secret.cipherFinish(ecb, wrapped.subarray(n - blk), CmsError, "cms/decrypt-failed", "the recovered CBC last block");
593
592
  var iv2 = Buffer.alloc(blk);
594
593
  for (var i = 0; i < blk; i++) iv2[i] = lastDec[i] ^ wrapped[n - 2 * blk + i];
595
- var d1 = nodeCrypto.createDecipheriv(alg, kek, iv2); d1.setAutoPadding(false);
594
+ var d1 = guard.crypto.decipher(alg, kek, iv2); guard.crypto.transformNoPadding(d1);
596
595
  pass1 = guard.secret.cipherFinish(d1, wrapped, CmsError, "cms/decrypt-failed", "the PWRI first-pass plaintext");
597
- var d2 = nodeCrypto.createDecipheriv(alg, kek, iv); d2.setAutoPadding(false);
596
+ var d2 = guard.crypto.decipher(alg, kek, iv); guard.crypto.transformNoPadding(d2);
598
597
  body = guard.secret.cipherFinish(d2, pass1, CmsError, "cms/decrypt-failed", "the PWRI plaintext block");
599
598
  var count = body[0];
600
599
  if (count < 1 || count + 4 > body.length) throw _fail();
@@ -670,8 +669,9 @@ function _ecCurveFromCert(cert) {
670
669
  function _ecCurveFromPrivateKey(keyDer) {
671
670
  var spki;
672
671
  try {
673
- spki = nodeCrypto.createPublicKey({ key: keyDer, format: "der", type: "pkcs8" })
674
- .export({ format: "der", type: "spki" });
672
+ spki = guard.crypto.exportKey(
673
+ guard.crypto.publicKey({ key: keyDer, format: "der", type: "pkcs8" }),
674
+ { format: "der", type: "spki" });
675
675
  } catch (_e) { return null; } // allow:swallow-unverified a key this runtime cannot read names no curve
676
676
  var alg = asn1.decode(spki).children[0];
677
677
  if (asn1.read.oid(alg.children[0]) !== O("ecPublicKey") || alg.children.length < 2) return null;
@@ -756,7 +756,7 @@ async function _verifyAuthenticatedData(parsed, km, opts, requireProtection) {
756
756
  _assertSupported(candidates[ci].ri, km);
757
757
  var macKey = await _acquireCek(candidates[ci].ri, km, opts);
758
758
  var macSubstitute = null;
759
- if (macKey == null || macKey.length < MAC_KEY_MIN_OCTETS) macSubstitute = nodeCrypto.randomBytes(MAC_KEY_MIN_OCTETS);
759
+ if (macKey == null || macKey.length < MAC_KEY_MIN_OCTETS) macSubstitute = guard.crypto.randomBytes(MAC_KEY_MIN_OCTETS);
760
760
  try {
761
761
  var key = await subtle.importKey("raw", macSubstitute || macKey, { name: "HMAC", hash: hash }, false, ["verify"]);
762
762
  if (!(await _subtleVerify(subtle, { name: "HMAC" }, key, Buffer.from(parsed.mac), preimage))) throw _fail();
package/lib/cms-digest.js CHANGED
@@ -26,7 +26,6 @@
26
26
  * attached or detached, constant-time comparison, fail-closed.
27
27
  */
28
28
 
29
- var nodeCrypto = require("node:crypto");
30
29
  var oid = require("./oid");
31
30
  var schemaCms = require("./schema-cms");
32
31
  var frameworkError = require("./framework-error");
@@ -101,7 +100,7 @@ async function _digest(content, opts) {
101
100
  var ctOid = O(ctName);
102
101
  if (!ctOid) throw _err("cms/bad-input", "opts.contentType is not a known OID name: " + guard.text.showValue(ctName));
103
102
 
104
- var value = nodeCrypto.createHash(NODE_DIGEST[alg]).update(raw).digest();
103
+ var value = guard.crypto.digest(NODE_DIGEST[alg], raw);
105
104
  var eciChildren = opts.detached === true
106
105
  ? [b.oid(ctOid)]
107
106
  : [b.oid(ctOid), b.explicit(0, b.octetString(raw))];
@@ -176,7 +175,7 @@ async function _verifyDigest(input, opts) {
176
175
  var covered = embedded != null
177
176
  ? guard.bytes.snapshotSource(embedded, CmsError, "cms/bad-input", "the encapsulated content")
178
177
  : supplied;
179
- var recomputed = nodeCrypto.createHash(NODE_DIGEST[alg]).update(covered).digest();
178
+ var recomputed = guard.crypto.digest(NODE_DIGEST[alg], covered);
180
179
  var matched = guard.crypto.constantTimeEqual(recomputed, parsed.digest);
181
180
  return guard.verdict.of({
182
181
  valid: matched,
@@ -4,7 +4,6 @@
4
4
  // @internal
5
5
  // @primitive pki.cms.encrypt block live in cms-verify.js, which re-exports this function (the
6
6
 
7
- var nodeCrypto = require("crypto");
8
7
  var asn1 = require("./asn1-der");
9
8
  var pkiBuild = require("./pki-build");
10
9
  var oid = require("./oid");
@@ -203,7 +202,7 @@ async function _buildKekri(cek, desc) {
203
202
 
204
203
  async function _buildPwri(cek, desc) {
205
204
  var iterations = pbes2.assertIterations(desc.iterations == null ? 600000 : desc.iterations, _err, "cms");
206
- var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") : nodeCrypto.randomBytes(16);
205
+ var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") : guard.crypto.randomBytes(16);
207
206
  var prf = desc.prf || "hmacWithSHA256";
208
207
  _prfHash(prf);
209
208
  var innerKeyBytes = 32;
@@ -213,7 +212,7 @@ async function _buildPwri(cek, desc) {
213
212
  var kek = Buffer.from(await subtle.deriveBits({ name: "PBKDF2", hash: _prfHash(prf), salt: salt, iterations: iterations }, kekKey, innerKeyBytes * 8));
214
213
  if (pwOwn.owned) guard.secret.zeroize(password, CmsError, "cms/bad-input", "the password encoding");
215
214
  try {
216
- var iv = nodeCrypto.randomBytes(16);
215
+ var iv = guard.crypto.randomBytes(16);
217
216
  var encryptedKey = _pwriWrapIv(kek, cek, iv);
218
217
  var kdfParams = pbes2.pbkdf2ParamsSeq(salt, iterations, prf);
219
218
  var kdfAlg = b.contextConstructed(0, Buffer.concat([b.oid(O("pbkdf2")), kdfParams]));
@@ -288,17 +287,17 @@ function _pwriFormat(cek) {
288
287
  var blk = 16;
289
288
  var padLen = body.length % blk === 0 ? 0 : blk - (body.length % blk);
290
289
  if (body.length + padLen < 2 * blk) padLen += (2 * blk - (body.length + padLen));
291
- var wrapped = Buffer.concat([body, nodeCrypto.randomBytes(padLen)]);
290
+ var wrapped = Buffer.concat([body, guard.crypto.randomBytes(padLen)]);
292
291
  guard.secret.zeroizeAll([check, body], CmsError, "cms/bad-input", "a PWRI formatting intermediate");
293
292
  return wrapped;
294
293
  }
295
294
  function _pwriWrapIv(kek, cek, iv) {
296
295
  var wk = _pwriFormat(cek);
297
296
  try {
298
- var c1 = nodeCrypto.createCipheriv("aes-256-cbc", kek, iv); c1.setAutoPadding(false);
297
+ var c1 = guard.crypto.cipher("aes-256-cbc", kek, iv); guard.crypto.transformNoPadding(c1);
299
298
  var pass1 = guard.secret.cipherFinish(c1, wk, CmsError, "cms/bad-input", "the PWRI first-pass ciphertext");
300
299
  var iv2 = pass1.subarray(pass1.length - 16);
301
- var c2 = nodeCrypto.createCipheriv("aes-256-cbc", kek, iv2); c2.setAutoPadding(false);
300
+ var c2 = guard.crypto.cipher("aes-256-cbc", kek, iv2); guard.crypto.transformNoPadding(c2);
302
301
  return guard.secret.cipherFinish(c2, pass1, CmsError, "cms/bad-input", "the PWRI wrapped key");
303
302
  } finally {
304
303
  guard.secret.zeroize(wk, CmsError, "cms/bad-input", "the PWRI plaintext block");
@@ -444,7 +443,7 @@ async function _encryptImpl(content, recipients, opts) {
444
443
  * them. */
445
444
  var contentBytes = contentStream ? null : guard.bytes.view(content, CmsError, "cms/bad-input", "content");
446
445
  var contentType = opts.contentType || "data";
447
- var cek = nodeCrypto.randomBytes(ca.keyBits / 8);
446
+ var cek = guard.crypto.randomBytes(ca.keyBits / 8);
448
447
 
449
448
  try {
450
449
  if (!Array.isArray(recipients)) return await _encryptedData(contentBytes, contentStream, recipients, ca, contentType, opts, cek);
@@ -477,7 +476,7 @@ async function _encStream(spec, stream) {
477
476
  }
478
477
 
479
478
  async function _envelopedData(contentBytes, contentStream, cek, ca, contentType, riNodes, recips) {
480
- var iv = nodeCrypto.randomBytes(16);
479
+ var iv = guard.crypto.randomBytes(16);
481
480
  var enc = contentStream
482
481
  ? (await _encStream({ algNode: "aes-" + ca.keyBits + "-cbc", key: cek, iv: iv }, contentStream)).ciphertext
483
482
  : pbes2.cbcEncrypt(cek, iv, contentBytes, ca.keyBits, CmsError, "cms/bad-input");
@@ -522,7 +521,7 @@ var AUTH_ENVELOPED_FORBIDDEN = intrinsic.assign(intrinsic.create(null), {
522
521
  });
523
522
 
524
523
  async function _authEnvelopedData(contentBytes, contentStream, cek, ca, contentType, opts, riNodes, recips) {
525
- var nonce = nodeCrypto.randomBytes(12);
524
+ var nonce = guard.crypto.randomBytes(12);
526
525
  var authAttrsDer = null, aad = Buffer.alloc(0);
527
526
  if (contentType !== "data" && !(opts.authAttrs && opts.authAttrs.length)) {
528
527
  throw _err("cms/bad-input", "AuthEnvelopedData with a non-data contentType requires authAttrs (RFC 5083 sec. 2.1)");
@@ -561,7 +560,7 @@ async function _encryptedData(contentBytes, contentStream, desc, ca, contentType
561
560
  " EncryptedData descriptor; that field is not read for this arm";
562
561
  });
563
562
  }
564
- var iv = nodeCrypto.randomBytes(16);
563
+ var iv = guard.crypto.randomBytes(16);
565
564
  var contentAlgNode, encKey;
566
565
  if (desc && desc.cek != null) {
567
566
  encKey = guard.bytes.view(desc.cek, CmsError, "cms/bad-input", "cek");
@@ -584,9 +583,9 @@ async function _encryptedDataPbes2(contentBytes, contentStream, desc, ca, conten
584
583
  var pwOwn2 = pbes2.passwordBytesOwned(desc.password, _err, "cms");
585
584
  var password = pwOwn2.bytes;
586
585
  var iterations = pbes2.assertIterations(desc.iterations == null ? 600000 : desc.iterations, _err, "cms");
587
- var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") : nodeCrypto.randomBytes(16);
586
+ var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") : guard.crypto.randomBytes(16);
588
587
  var prf = desc.prf || "hmacWithSHA256";
589
- var key = nodeCrypto.pbkdf2Sync(password, salt, iterations, ca.keyBits / 8, pbes2.prfNodeByName(prf, _err, "cms"));
588
+ var key = guard.crypto.pbkdf2(password, salt, iterations, ca.keyBits / 8, pbes2.prfNodeByName(prf, _err, "cms"));
590
589
  if (pwOwn2.owned) guard.secret.zeroize(password, CmsError, "cms/bad-input", "the password encoding");
591
590
  try {
592
591
  var enc = contentStream
@@ -602,10 +601,10 @@ async function _encryptedDataPbes2(contentBytes, contentStream, desc, ca, conten
602
601
  }
603
602
 
604
603
  function _gcmEncrypt(key, nonce, plaintext, aad, keyBits, tagLen) {
605
- var c = nodeCrypto.createCipheriv("aes-" + keyBits + "-gcm", key, nonce, { authTagLength: tagLen });
606
- if (aad && aad.length) c.setAAD(aad);
604
+ var c = guard.crypto.cipher("aes-" + keyBits + "-gcm", key, nonce, { authTagLength: tagLen });
605
+ if (aad && aad.length) guard.crypto.transformSetAAD(c, aad);
607
606
  var ct = guard.secret.cipherFinish(c, plaintext, CmsError, "cms/bad-input", "a content-encryption intermediate");
608
- return { ct: ct, tag: c.getAuthTag() };
607
+ return { ct: ct, tag: guard.crypto.cipherAuthTag(c) };
609
608
  }
610
609
 
611
610
  function _tlvHeaderLen(der) {
@@ -682,7 +681,7 @@ async function _authenticateImpl(content, recipients, opts) {
682
681
  var contentType = opts.contentType || "data";
683
682
  if (contentType !== "data" && !withAttrs) throw _err("cms/bad-input", "AuthenticatedData with a non-data contentType requires authenticated attributes (RFC 5652 sec. 9.1)");
684
683
 
685
- var macKey = nodeCrypto.randomBytes(MAC_KEY_OCTETS);
684
+ var macKey = guard.crypto.randomBytes(MAC_KEY_OCTETS);
686
685
  try {
687
686
  var recips = [];
688
687
  var consumedAuth = {};
@@ -23,7 +23,6 @@
23
23
  var asn1 = require("./asn1-der");
24
24
  var oid = require("./oid");
25
25
  var webcrypto = require("./webcrypto");
26
- var nodeCrypto = require("node:crypto");
27
26
  var frameworkError = require("./framework-error");
28
27
  var guard = require("./guard-all");
29
28
  var intrinsic = require("./guard-intrinsic");
@@ -115,11 +114,11 @@ function _mlkemDecaps(d, seed, mlkemCT) {
115
114
  function _ecPubFromPoint(d, point) {
116
115
  if (point.length < 1 || point[0] !== 0x04) throw _err("kem/bad-key", "the EC component point is not in uncompressed form");
117
116
  var spki = _b.sequence([_b.sequence([_b.oid(oid.byName("ecPublicKey")), _b.oid(oid.byName(d.trad.curve))]), _b.bitString(point, 0)]);
118
- return nodeCrypto.createPublicKey({ key: spki, format: "der", type: "spki" });
117
+ return guard.crypto.publicKey({ key: spki, format: "der", type: "spki" });
119
118
  }
120
119
  function _okpPubFromRaw(d, raw) {
121
120
  var spki = _b.sequence([_b.sequence([_b.oid(oid.byName(d.trad.curve))]), _b.bitString(raw, 0)]);
122
- return nodeCrypto.createPublicKey({ key: spki, format: "der", type: "spki" });
121
+ return guard.crypto.publicKey({ key: spki, format: "der", type: "spki" });
123
122
  }
124
123
  /** @internal The encoding is this helper's own allocation and holds the traditional private scalar, so
125
124
  * it is cleared here. A caller's own cleanup cannot reach a buffer it never sees, and both the
@@ -127,13 +126,13 @@ function _okpPubFromRaw(d, raw) {
127
126
  function _okpPrivFromRaw(d, raw) {
128
127
  var p8 = _b.sequence([_b.integer(0n), _b.sequence([_b.oid(oid.byName(d.trad.curve))]), _b.octetString(_b.octetString(raw))]);
129
128
  try {
130
- return nodeCrypto.createPrivateKey({ key: p8, format: "der", type: "pkcs8" });
129
+ return guard.crypto.privateKey({ key: p8, format: "der", type: "pkcs8" });
131
130
  } finally {
132
131
  guard.secret.zeroize(p8, KemError, "kem/bad-input", "the " + d.trad.curve + " component key encoding");
133
132
  }
134
133
  }
135
134
  function _rawPubOf(keyObject) {
136
- var spki = keyObject.export({ format: "der", type: "spki" });
135
+ var spki = guard.crypto.exportKey(keyObject, { format: "der", type: "spki" });
137
136
  return Buffer.from(asn1.read.bitString(asn1.decode(spki).children[1]).bytes);
138
137
  }
139
138
 
@@ -143,12 +142,12 @@ function _tradEncaps(d, tradPK) {
143
142
  var pub;
144
143
  try {
145
144
  asn1.decode(tradPK);
146
- pub = nodeCrypto.createPublicKey({ key: tradPK, format: "der", type: "pkcs1" });
145
+ pub = guard.crypto.publicKey({ key: tradPK, format: "der", type: "pkcs1" });
147
146
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component public key is not a valid RSAPublicKey", e)); }
148
- if (pub.asymmetricKeyDetails.modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
149
- var ss = Buffer.from(nodeCrypto.randomBytes(RSA_SS));
147
+ if (guard.crypto.keyDetails(pub).modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
148
+ var ss = Buffer.from(guard.crypto.randomBytes(RSA_SS));
150
149
  var ct;
151
- try { ct = Buffer.from(nodeCrypto.publicEncrypt({ key: pub, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, ss)); }
150
+ try { ct = Buffer.from(guard.crypto.publicEncrypt({ key: pub, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, ss)); }
152
151
  catch (e) {
153
152
  guard.secret.zeroize(ss, KemError, "kem/bad-input", "the RSA-OAEP component secret");
154
153
  return _promiseReject(_Promise, _err("kem/bad-key", "the RSA-OAEP component encryption failed", e));
@@ -158,8 +157,8 @@ function _tradEncaps(d, tradPK) {
158
157
  var dh, dhCt;
159
158
  try {
160
159
  var recip = trad.kind === "ec" ? _ecPubFromPoint(d, tradPK) : _okpPubFromRaw(d, tradPK);
161
- var eph = trad.kind === "ec" ? nodeCrypto.generateKeyPairSync("ec", { namedCurve: trad.node }) : nodeCrypto.generateKeyPairSync(trad.curve.toLowerCase());
162
- dh = Buffer.from(nodeCrypto.diffieHellman({ privateKey: eph.privateKey, publicKey: recip }));
160
+ var eph = trad.kind === "ec" ? guard.crypto.generateKeyPair("ec", { namedCurve: trad.node }) : guard.crypto.generateKeyPair(trad.curve.toLowerCase());
161
+ dh = Buffer.from(guard.crypto.diffieHellman({ privateKey: eph.privateKey, publicKey: recip }));
163
162
  dhCt = _rawPubOf(eph.publicKey);
164
163
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the " + trad.curve + " public key is invalid", e)); }
165
164
  return _promiseResolve(_Promise, { ss: dh, ct: dhCt });
@@ -171,37 +170,38 @@ function _tradDecaps(d, tradSK, tradCT) {
171
170
  var priv;
172
171
  try {
173
172
  asn1.decode(tradSK);
174
- priv = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "pkcs1" });
173
+ priv = guard.crypto.privateKey({ key: tradSK, format: "der", type: "pkcs1" });
175
174
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component private key is not a valid RSAPrivateKey", e)); }
176
- if (priv.asymmetricKeyDetails.modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
175
+ if (guard.crypto.keyDetails(priv).modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
177
176
  var ss;
178
- try { ss = Buffer.from(nodeCrypto.privateDecrypt({ key: priv, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, tradCT)); }
177
+ try { ss = Buffer.from(guard.crypto.privateDecrypt({ key: priv, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, tradCT)); }
179
178
  catch (_e) { return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the RSA-OAEP component decryption failed")); }
180
179
  if (ss.length !== RSA_SS) {
181
180
  guard.secret.zeroize(ss, KemError, "kem/bad-input", "the RSA-OAEP component secret");
182
181
  return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the RSA-OAEP component decryption failed"));
183
182
  }
184
- return _promiseResolve(_Promise, { ss: ss, tradPK: Buffer.from(nodeCrypto.createPublicKey(priv).export({ format: "der", type: "pkcs1" })) });
183
+ return _promiseResolve(_Promise, { ss: ss,
184
+ tradPK: Buffer.from(guard.crypto.exportKey(guard.crypto.publicKey(priv), { format: "der", type: "pkcs1" })) });
185
185
  }
186
186
  var priv2, eph;
187
187
  try {
188
188
  if (trad.kind === "ec") {
189
189
  asn1.decode(tradSK);
190
- priv2 = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "sec1" });
190
+ priv2 = guard.crypto.privateKey({ key: tradSK, format: "der", type: "sec1" });
191
191
  } else {
192
192
  priv2 = _okpPrivFromRaw(d, tradSK);
193
193
  }
194
194
  eph = trad.kind === "ec" ? _ecPubFromPoint(d, tradCT) : _okpPubFromRaw(d, tradCT);
195
195
  } catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the " + trad.curve + " key material is invalid", e)); }
196
196
  var dh;
197
- try { dh = Buffer.from(nodeCrypto.diffieHellman({ privateKey: priv2, publicKey: eph })); }
197
+ try { dh = Buffer.from(guard.crypto.diffieHellman({ privateKey: priv2, publicKey: eph })); }
198
198
  catch (e) { return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the " + trad.curve + " Diffie-Hellman failed", e)); }
199
199
  /** @internal The same canonical point the derivation states, read from the one function that spells
200
200
  * it. The combiner hashes these bytes, so a stored spelling here and a generated one there would
201
201
  * reach different secrets from the two sides of one key. */
202
202
  var tradPK;
203
203
  try {
204
- tradPK = trad.kind === "ec" ? _ecPointOf(d, tradSK) : _rawPubOf(nodeCrypto.createPublicKey(priv2));
204
+ tradPK = trad.kind === "ec" ? _ecPointOf(d, tradSK) : _rawPubOf(guard.crypto.publicKey(priv2));
205
205
  } catch (e) {
206
206
  /** @internal The agreement already produced a secret, and this rejection happens after it, so the
207
207
  * secret is wiped here: the caller's settle-or-wipe covers a value it was handed, and a rejected
@@ -371,9 +371,7 @@ function _ecPointOf(d, tradSK) {
371
371
  var scalar = _ecScalarOf(d, tradSK);
372
372
  var point;
373
373
  try {
374
- var ecdh = nodeCrypto.createECDH(d.trad.node);
375
- ecdh.setPrivateKey(scalar);
376
- point = ecdh.getPublicKey(null, "uncompressed");
374
+ point = guard.crypto.ecPointFromScalar(d.trad.node, scalar);
377
375
  } catch (e) {
378
376
  if (e instanceof KemError) throw e;
379
377
  throw _err("kem/bad-key", "the EC component scalar does not generate a point on " + d.trad.node, e);
@@ -418,18 +416,18 @@ function _tradPubOf(d, tradSK) {
418
416
  var rp;
419
417
  try {
420
418
  asn1.decode(tradSK);
421
- rp = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "pkcs1" });
419
+ rp = guard.crypto.privateKey({ key: tradSK, format: "der", type: "pkcs1" });
422
420
  } catch (e) { throw _err("kem/bad-key", "the RSA component private key is not a valid RSAPrivateKey", e); }
423
- if (rp.asymmetricKeyDetails.modulusLength !== trad.bits) {
421
+ if (guard.crypto.keyDetails(rp).modulusLength !== trad.bits) {
424
422
  throw _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)");
425
423
  }
426
- return Buffer.from(nodeCrypto.createPublicKey(rp).export({ format: "der", type: "pkcs1" }));
424
+ return Buffer.from(guard.crypto.exportKey(guard.crypto.publicKey(rp), { format: "der", type: "pkcs1" }));
427
425
  }
428
426
  var priv;
429
427
  try {
430
428
  if (trad.kind === "ec") {
431
429
  asn1.decode(tradSK);
432
- priv = nodeCrypto.createPrivateKey({ key: tradSK, format: "der", type: "sec1" });
430
+ priv = guard.crypto.privateKey({ key: tradSK, format: "der", type: "sec1" });
433
431
  } else {
434
432
  priv = _okpPrivFromRaw(d, tradSK);
435
433
  }
@@ -439,7 +437,8 @@ function _tradPubOf(d, tradSK) {
439
437
  * public key nothing can use, so the two are held to each other here. Decapsulation reaches the same
440
438
  * conclusion by failing the agreement; a derivation performs no operation that would notice. */
441
439
  if (trad.kind === "ec") {
442
- var named = priv.asymmetricKeyDetails && priv.asymmetricKeyDetails.namedCurve;
440
+ var privDetails = guard.crypto.keyDetails(priv);
441
+ var named = privDetails && privDetails.namedCurve;
443
442
  if (named !== trad.node) {
444
443
  throw _err("kem/bad-key", "the EC component is on " + guard.text.showValue(named) + ", and " + d.name + " names " + trad.node);
445
444
  }
@@ -450,7 +449,7 @@ function _tradPubOf(d, tradSK) {
450
449
  * point stored beside it cannot stand in for one it does not generate. */
451
450
  return _ecPointOf(d, tradSK);
452
451
  }
453
- return _rawPubOf(nodeCrypto.createPublicKey(priv));
452
+ return _rawPubOf(guard.crypto.publicKey(priv));
454
453
  }
455
454
 
456
455
  /** @internal The composite `SubjectPublicKeyInfo` for a composite ML-KEM private key. The runtime key
@@ -488,8 +487,8 @@ async function _publicFromPrivate(privateKey) {
488
487
  * copy of the seed and is registered as one. */
489
488
  var seedPkcs8 = _mlkemSeedPkcs8(d, seed);
490
489
  guard.list.append(secrets, seedPkcs8);
491
- var mlPriv = nodeCrypto.createPrivateKey({ key: seedPkcs8, format: "der", type: "pkcs8" });
492
- ek = _rawPubOf(nodeCrypto.createPublicKey(mlPriv));
490
+ var mlPriv = guard.crypto.privateKey({ key: seedPkcs8, format: "der", type: "pkcs8" });
491
+ ek = _rawPubOf(guard.crypto.publicKey(mlPriv));
493
492
  } catch (e) {
494
493
  if (e instanceof KemError) throw e;
495
494
  throw _err("kem/bad-key", "the ML-KEM component private key is invalid", e);
package/lib/crmf-sign.js CHANGED
@@ -17,12 +17,6 @@
17
17
  * @card Build a CRMF CertReqMessages with a signature proof of possession.
18
18
  */
19
19
 
20
- var nodeCrypto = require("node:crypto");
21
- /** @internal Bound at module load, like every other capture here: the proof below decides what it
22
- * agrees and what it hashes, so a replacement swapped in afterwards must not be able to steer it. */
23
- var _diffieHellman = nodeCrypto.diffieHellman;
24
- var _createPublicKey = nodeCrypto.createPublicKey;
25
- var _createPrivateKey = nodeCrypto.createPrivateKey;
26
20
  var asn1 = require("./asn1-der");
27
21
  var oid = require("./oid");
28
22
  var x509 = require("./schema-x509");
@@ -345,7 +339,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
345
339
  _assertAgreementExponent(pkcs3, "the authority certificate's key");
346
340
  }
347
341
  }
348
- try { caPub = _createPublicKey({ key: caSpkiBytes, format: "der", type: "spki" }); }
342
+ try { caPub = guard.crypto.publicKey({ key: caSpkiBytes, format: "der", type: "spki" }); }
349
343
  catch (e) { throw _err("crmf/bad-popo", "the authority certificate does not carry a key this runtime can agree with", e); }
350
344
  /** @internal The snapshot of the caller's key is this function's own copy of private material, so it
351
345
  * is registered for the wipe below rather than left to the argument boundary, which clears what it
@@ -357,7 +351,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
357
351
  /** @internal Inside the cleanup scope, because the import can throw AFTER the snapshot exists: a
358
352
  * catch that returned from out here would leave that copy of private material behind. */
359
353
  try {
360
- if (pop.key && typeof pop.key === "object" && pop.key.asymmetricKeyType != null) {
354
+ if (guard.crypto.keyTypeOf(pop.key) != null) {
361
355
  eePriv = pop.key;
362
356
  } else if (pop.key && typeof pop.key === "object" && pop.key.type === "private" &&
363
357
  typeof pop.key.export === "function") {
@@ -366,10 +360,10 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
366
360
  * applies here: supporting the encoding for a caller holding bytes and refusing the caller
367
361
  * holding the key those bytes import to would be the same key admitted one way. The export
368
362
  * is this function's own copy of private material and is cleared with the rest. */
369
- keySnapshot = pop.key.export({ format: "der", type: "pkcs8" });
363
+ keySnapshot = guard.crypto.exportKey(pop.key, { format: "der", type: "pkcs8" });
370
364
  translated = _x942PrivToPkcs3(keySnapshot);
371
365
  eePriv = translated !== null
372
- ? _createPrivateKey({ key: translated, format: "der", type: "pkcs8" })
366
+ ? guard.crypto.privateKey({ key: translated, format: "der", type: "pkcs8" })
373
367
  : pop.key;
374
368
  } else if (guard.bytes.isByteSource(pop.key)) {
375
369
  keySnapshot = guard.bytes.snapshotSource(pop.key, CrmfError, "crmf/bad-popo", "the requester's private key");
@@ -377,7 +371,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
377
371
  * copy of the private value, and an import that throws after it exists must not leave it
378
372
  * behind. The wipe below clears whatever was made, on every way out. */
379
373
  translated = _x942PrivToPkcs3(keySnapshot);
380
- eePriv = _createPrivateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
374
+ eePriv = guard.crypto.privateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
381
375
  } else {
382
376
  /** @internal A PEM key reaches the same conversion: it is the same key in the same encoding
383
377
  * with an armor around it, so admitting one form and not the other would support X9.42 for a
@@ -386,9 +380,9 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
386
380
  if (pemDer !== null) {
387
381
  keySnapshot = pemDer;
388
382
  translated = _x942PrivToPkcs3(keySnapshot);
389
- eePriv = _createPrivateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
383
+ eePriv = guard.crypto.privateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
390
384
  } else {
391
- eePriv = _createPrivateKey(pop.key);
385
+ eePriv = guard.crypto.privateKey(pop.key);
392
386
  }
393
387
  }
394
388
  } catch (e) {
@@ -402,7 +396,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
402
396
  * something this request never asked to have certified. The encryptedKey arm holds its enclosed
403
397
  * key to the same rule. */
404
398
  var eeSpki;
405
- try { eeSpki = _createPublicKey(eePriv).export({ format: "der", type: "spki" }); }
399
+ try { eeSpki = guard.crypto.exportKey(guard.crypto.publicKey(eePriv), { format: "der", type: "spki" }); }
406
400
  catch (e) { throw _err("crmf/bad-popo", "the public half of pop.key could not be derived to check it against the requested key", e); }
407
401
  /** @internal Compared as keys, not as bytes. A PKCS#3 DHParameter carries an optional
408
402
  * privateValueLength, so one finite-field key has more than one valid SubjectPublicKeyInfo and a
@@ -449,7 +443,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
449
443
  * with parameters g and p, agreeing `g^xy mod p`. An elliptic-curve or montgomery pair agrees a
450
444
  * secret through the same call and would be emitted under the same OID, which names an operation
451
445
  * the recipient would not be performing. */
452
- if (eePriv.asymmetricKeyType !== "dh" || caPub.asymmetricKeyType !== "dh") {
446
+ if (guard.crypto.keyType(eePriv) !== "dh" || guard.crypto.keyType(caPub) !== "dh") {
453
447
  /** @internal A key this runtime imported but did not classify reports no asymmetricKeyType, which
454
448
  * is what an X9.42 dhpublicnumber SubjectPublicKeyInfo does here where the PKCS#3 dhKeyAgreement
455
449
  * form is classified. The agreement refuses such a key on its own, so naming the unrecognized
@@ -459,7 +453,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
459
453
  }
460
454
  /** @internal The agreement's own Buffer, not a copy of it: wrapping it would leave the original
461
455
  * holding the secret with nothing to clear it. */
462
- try { zz = _diffieHellman({ privateKey: eePriv, publicKey: caPub }); }
456
+ try { zz = guard.crypto.diffieHellman({ privateKey: eePriv, publicKey: caPub }); }
463
457
  catch (e) { throw _err("crmf/bad-popo", "the requester's key and the authority's key did not agree a secret; this proof needs a key on the authority's own parameters (RFC 4211 sec. 4.3)", e); }
464
458
  /** @internal K = SHA1(LeadingInfo | ZZ | TrailingInfo) (RFC 2875 sec. 3, step 3c), under the
465
459
  * digest the proof's own algorithm identifier names. */
@@ -762,7 +756,7 @@ function _x942ToPkcs3(spkiBytes, what) {
762
756
  /** @internal How a key reads in the refusal above. A key the runtime imported without classifying
763
757
  * carries no asymmetricKeyType, and reporting that as a type name says nothing an operator can act on. */
764
758
  function _keyTypeLabel(what, key) {
765
- var type = key && key.asymmetricKeyType;
759
+ var type = guard.crypto.keyTypeOf(key);
766
760
  if (typeof type !== "string" || type === "") {
767
761
  return what + " carries an algorithm this runtime does not recognize as a key it can agree with";
768
762
  }