@blamejs/pki 0.6.14 → 0.6.16

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.
Files changed (112) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/lib/acme.js +59 -815
  3. package/lib/asn1-der.js +7 -245
  4. package/lib/attrcert-sign.js +12 -260
  5. package/lib/attrcert-verify.js +1 -7
  6. package/lib/byte-reader.js +0 -8
  7. package/lib/byte-writer.js +0 -11
  8. package/lib/cbor-det.js +0 -54
  9. package/lib/cmc-build.js +15 -357
  10. package/lib/cmc-verify.js +6 -239
  11. package/lib/cmp-build.js +41 -317
  12. package/lib/cmp-session.js +73 -760
  13. package/lib/cmp-verify.js +32 -488
  14. package/lib/cms-compress.js +3 -32
  15. package/lib/cms-decrypt.js +29 -294
  16. package/lib/cms-encrypt.js +14 -234
  17. package/lib/cms-sign.js +29 -324
  18. package/lib/cms-verify.js +9 -500
  19. package/lib/composite-kem.js +2 -102
  20. package/lib/composite-sig.js +1 -77
  21. package/lib/constants.js +0 -249
  22. package/lib/crl-sign.js +9 -237
  23. package/lib/crl-verify.js +1 -10
  24. package/lib/crmf-sign.js +19 -198
  25. package/lib/crmf-verify.js +1 -12
  26. package/lib/csr-sign.js +3 -34
  27. package/lib/csr-verify.js +1 -12
  28. package/lib/ct.js +28 -253
  29. package/lib/edwards-point.js +10 -44
  30. package/lib/est.js +28 -764
  31. package/lib/framework-error.js +4 -182
  32. package/lib/guard-all.js +1 -58
  33. package/lib/guard-async.js +1 -36
  34. package/lib/guard-bytes.js +6 -650
  35. package/lib/guard-compress.js +5 -102
  36. package/lib/guard-crypto.js +1 -40
  37. package/lib/guard-der.js +2 -93
  38. package/lib/guard-encoding.js +2 -60
  39. package/lib/guard-header.js +1 -36
  40. package/lib/guard-identifier.js +7 -531
  41. package/lib/guard-intrinsic.js +1 -150
  42. package/lib/guard-json.js +10 -73
  43. package/lib/guard-limits.js +1 -77
  44. package/lib/guard-list.js +1 -49
  45. package/lib/guard-name.js +3 -209
  46. package/lib/guard-parsed.js +7 -335
  47. package/lib/guard-range.js +1 -71
  48. package/lib/guard-secret.js +1 -102
  49. package/lib/guard-text.js +1 -64
  50. package/lib/guard-time.js +1 -97
  51. package/lib/hpke.js +3 -105
  52. package/lib/http-digest.js +14 -142
  53. package/lib/http-retry-after.js +1 -47
  54. package/lib/http-transport.js +21 -131
  55. package/lib/inspect.js +30 -284
  56. package/lib/ip-utils.js +6 -47
  57. package/lib/jose.js +7 -142
  58. package/lib/key.js +2 -67
  59. package/lib/lint.js +9 -194
  60. package/lib/merkle.js +1 -27
  61. package/lib/mime.js +9 -82
  62. package/lib/ocsp-request-verify.js +1 -14
  63. package/lib/ocsp-verify.js +1 -82
  64. package/lib/ocsp.js +11 -169
  65. package/lib/oid.js +5 -337
  66. package/lib/path-validate.js +103 -1492
  67. package/lib/pbes2.js +2 -89
  68. package/lib/pkcs12-build.js +31 -379
  69. package/lib/pki-build.js +64 -290
  70. package/lib/rc2.js +2 -18
  71. package/lib/rfc3339.js +4 -27
  72. package/lib/scep.js +140 -286
  73. package/lib/schema-all.js +0 -122
  74. package/lib/schema-attrcert.js +4 -146
  75. package/lib/schema-c509.js +153 -802
  76. package/lib/schema-cmc.js +5 -220
  77. package/lib/schema-cmp.js +2 -223
  78. package/lib/schema-cms.js +13 -427
  79. package/lib/schema-crl.js +5 -68
  80. package/lib/schema-crmf.js +6 -167
  81. package/lib/schema-csr.js +1 -54
  82. package/lib/schema-csrattrs.js +2 -87
  83. package/lib/schema-engine.js +0 -152
  84. package/lib/schema-ocsp.js +0 -117
  85. package/lib/schema-pkcs12.js +2 -93
  86. package/lib/schema-pkcs8.js +3 -35
  87. package/lib/schema-pkix.js +24 -655
  88. package/lib/schema-smime.js +0 -54
  89. package/lib/schema-tsp.js +3 -99
  90. package/lib/schema-x509.js +4 -63
  91. package/lib/shbs.js +11 -95
  92. package/lib/sign-scheme.js +2 -97
  93. package/lib/sigstore.js +9 -169
  94. package/lib/sleep.js +2 -8
  95. package/lib/smime.js +15 -408
  96. package/lib/tls-cert-compress.js +0 -62
  97. package/lib/trust.js +19 -185
  98. package/lib/tsp-sign.js +16 -270
  99. package/lib/validator-all.js +1 -30
  100. package/lib/validator-attcert.js +2 -46
  101. package/lib/validator-cose.js +2 -153
  102. package/lib/validator-keydesc.js +1 -37
  103. package/lib/validator-sig.js +1 -46
  104. package/lib/validator-tls.js +1 -88
  105. package/lib/validator-tpm.js +19 -122
  106. package/lib/verify-seam.js +1 -24
  107. package/lib/webauthn-mds.js +3 -400
  108. package/lib/webauthn.js +12 -833
  109. package/lib/webcrypto.js +5 -485
  110. package/lib/x509-sign.js +4 -108
  111. package/package.json +1 -1
  112. package/sbom.cdx.json +6 -6
package/lib/pbes2.js CHANGED
@@ -1,14 +1,7 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // Copyright (c) blamejs contributors
3
3
  "use strict";
4
- //
5
- // @internal -- the RFC 8018 PBES2 / PBKDF2 primitives, the single home shared by pki.cms EncryptedData / PWRI
6
- // password encryption and pki.key EncryptedPrivateKeyInfo (RFC 5958). Error-factory-parameterized like the
7
- // guard family: every reject goes through the caller's `E(code, msg, cause)` full-code factory plus a domain
8
- // `prefix`, so pki.cms keeps cms/* codes and pki.key keeps key/* codes off one implementation. Extracted
9
- // behavior-preservingly from cms-encrypt.js and cms-decrypt.js; the shipped CMS PBES2 tests are the guard.
10
- // A shape here that cannot route through a guard stays with its caller; the reusable PBES2 shape lives here
11
- // so a fourth copy (the drift a reviewer flags) cannot re-accrete.
4
+ // @internal
12
5
 
13
6
  var nodeCrypto = require("crypto");
14
7
  var asn1 = require("./asn1-der");
@@ -20,15 +13,9 @@ var C = require("./constants");
20
13
  var b = asn1.build;
21
14
  function O(n) { return oid.byName(n); }
22
15
 
23
- // PBKDF2 prf tables: the OID name -> node digest (encrypt names the prf) and the OID -> node digest (decrypt
24
- // reads the OID). One source, both directions.
25
16
  var PRF_NODE_BY_NAME = { hmacWithSHA1: "sha1", hmacWithSHA256: "sha256", hmacWithSHA384: "sha384", hmacWithSHA512: "sha512" };
26
17
  var PRF_NODE_BY_OID = {}; Object.keys(PRF_NODE_BY_NAME).forEach(function (n) { PRF_NODE_BY_OID[O(n)] = PRF_NODE_BY_NAME[n]; });
27
18
 
28
- // content-encryption OID -> AES key bits (CBC + GCM). The PBES2 encryptionScheme + CMS content cipher table.
29
- // CONTENT_MODE rides the same rows so a cipher can never be present for its key length but absent for its
30
- // mode: key length alone does not distinguish an AEAD cipher from a plain one, and a consumer that resolves
31
- // only the length would open content in the wrong mode whenever the two happen to share a key size.
32
19
  var CONTENT_KEYBITS = {}, CONTENT_MODE = {};
33
20
  [["aes128-CBC", 128, "cbc"], ["aes192-CBC", 192, "cbc"], ["aes256-CBC", 256, "cbc"],
34
21
  ["aes128-GCM", 128, "gcm"], ["aes192-GCM", 192, "gcm"], ["aes256-GCM", 256, "gcm"]].forEach(function (r) {
@@ -36,15 +23,8 @@ var CONTENT_KEYBITS = {}, CONTENT_MODE = {};
36
23
  CONTENT_MODE[O(r[0])] = r[2];
37
24
  });
38
25
 
39
- // A password is an octet string (RFC 8018 sec. 2): a string is UTF-8-encoded deterministically (correct for
40
- // non-ASCII, and byte-identical to OpenSSL), a Buffer/Uint8Array used verbatim.
41
26
  function passwordBytes(p, E, prefix) { return passwordBytesOwned(p, E, prefix).bytes; }
42
27
 
43
- // The same conversion, reporting OWNERSHIP. A string or Uint8Array password is encoded into a fresh
44
- // Buffer this toolkit allocated -- a credential copy that must be cleared once the derivation has
45
- // consumed it -- while a caller-supplied Buffer is BORROWED and must be left intact. Without this
46
- // distinction a call site can only be safe by leaving every password encoding readable, which is
47
- // the common case, since a password arrives as a string far more often than as a Buffer.
48
28
  function passwordBytesOwned(p, E, prefix) {
49
29
  if (Buffer.isBuffer(p)) return { bytes: p, owned: false };
50
30
  if (p instanceof Uint8Array) return { bytes: Buffer.from(p), owned: true };
@@ -52,15 +32,12 @@ function passwordBytesOwned(p, E, prefix) {
52
32
  throw E(prefix + "/bad-input", "a password must be a string, Buffer, or Uint8Array");
53
33
  }
54
34
 
55
- // iterationCount for a PRODUCED PBES2/PWRI structure: a positive integer at or below the cap the decryptor
56
- // enforces, so a structure we emit is always one we can read back (config-time throw on a bad value).
57
35
  function assertIterations(n, E, prefix) {
58
36
  if (typeof n !== "number" || !isFinite(n) || n < 1 || Math.floor(n) !== n) throw E(prefix + "/bad-input", "iterations must be a positive integer");
59
37
  if (n > C.LIMITS.PBKDF2_MAX_ITERATIONS) throw E(prefix + "/bad-input", "iterations exceeds the " + C.LIMITS.PBKDF2_MAX_ITERATIONS + " cap");
60
38
  return n;
61
39
  }
62
40
 
63
- // Bound a PRODUCED salt to the same cap the decryptor enforces.
64
41
  function assertSalt(salt, E, prefix) {
65
42
  guard.limits.byteCap(salt, C.LIMITS.PBKDF2_MAX_SALT, E, prefix + "/bad-input", "salt");
66
43
  return salt;
@@ -69,28 +46,18 @@ function assertSalt(salt, E, prefix) {
69
46
  function prfNodeByName(prf, E, prefix) { if (!PRF_NODE_BY_NAME[prf]) throw E(prefix + "/bad-input", "unsupported prf " + JSON.stringify(prf)); return PRF_NODE_BY_NAME[prf]; }
70
47
  function prfNodeByOid(oidStr, E, prefix) { if (!PRF_NODE_BY_OID[oidStr]) throw E(prefix + "/unsupported-algorithm", "unsupported PBKDF2 prf " + oidStr); return PRF_NODE_BY_OID[oidStr]; }
71
48
 
72
- // PBKDF2-params { salt OCTET STRING, iterationCount INTEGER, prf DEFAULT hmacWithSHA1 }. prf equal to the
73
- // DEFAULT (hmacWithSHA1) MUST be omitted on encode (X.690 sec. 11.5 / RFC 8018 App. A.2); every other prf is
74
- // an hmacWithSHA_n AlgorithmIdentifier carrying NULL parameters.
75
49
  function pbkdf2ParamsSeq(salt, iterations, prf) {
76
50
  var kids = [b.octetString(salt), b.integer(BigInt(iterations))];
77
51
  if (prf !== "hmacWithSHA1") kids.push(b.sequence([b.oid(O(prf)), b.nullValue()]));
78
52
  return b.sequence(kids);
79
53
  }
80
54
 
81
- // The PBES2 AlgorithmIdentifier: SEQUENCE { id-PBES2, SEQUENCE { keyDerivationFunc PBKDF2, encryptionScheme } }.
82
- // The single home for the CMS EncryptedData contentEncryptionAlgorithm and the RFC 5958 EncryptedPrivateKeyInfo
83
- // encryptionAlgorithm: both wrap the same PBES2 structure around a PBKDF2 KDF plus an AES-CBC scheme whose
84
- // IV rides in the encryptionScheme parameter. `cipherName` is a registry NAME (an AES-CBC OID name).
85
55
  function pbes2AlgId(salt, iterations, prf, cipherName, iv) {
86
56
  var kdf = b.sequence([b.oid(O("pbkdf2")), pbkdf2ParamsSeq(salt, iterations, prf)]);
87
57
  var encScheme = b.sequence([b.oid(O(cipherName)), b.octetString(iv)]);
88
58
  return b.sequence([b.oid(O("pbes2")), b.sequence([kdf, encScheme])]);
89
59
  }
90
60
 
91
- // SEQUENCE structural guards -- a malformed (primitive / too-short) attacker-controlled parameter SEQUENCE is
92
- // a typed E(prefix + "/bad-input"), never a raw `.children` dereference fault (a PBES2 structure is public,
93
- // not a decrypt oracle).
94
61
  function requireChildren(node, minLen, what, E, prefix) {
95
62
  if (!node || !node.children || node.children.length < minLen) throw E(prefix + "/bad-input", "malformed " + what);
96
63
  return node.children;
@@ -100,9 +67,6 @@ function seqChildren(paramsDer, minLen, what, E, prefix) {
100
67
  return requireChildren(asn1.decode(paramsDer), minLen, what, E, prefix);
101
68
  }
102
69
 
103
- // Strict PBKDF2-params decode: salt (capped before derivation), iterationCount (positiveInt31 + cap, downward-
104
- // overridable via a validated-positive-int opts.maxIterations so Math.min(NaN, cap) cannot silently disable
105
- // the DoS cap), prf. Returns { salt, iterations, prfNode }.
106
70
  function parsePbkdf2Params(paramsDer, opts, E, prefix, strictPrf) {
107
71
  var node = Buffer.isBuffer(paramsDer) ? asn1.decode(paramsDer) : paramsDer;
108
72
  var kids = requireChildren(node, 2, "PBKDF2 parameters", E, prefix);
@@ -120,8 +84,6 @@ function parsePbkdf2Params(paramsDer, opts, E, prefix, strictPrf) {
120
84
  var ch = node.children[i];
121
85
  if (ch.tagClass === "universal" && ch.tagNumber === asn1.TAGS.SEQUENCE) {
122
86
  var prfOid = asn1.read.oid(ch.children[0]);
123
- // X.690 sec. 11.5 / RFC 8018 App. A.2: a prf equal to the DEFAULT (hmacWithSHA1 with NULL parameters)
124
- // MUST be omitted -- an explicit encoding of it is non-canonical. A strictPrf caller rejects it.
125
87
  if (strictPrf && prfOid === O("hmacWithSHA1") && ch.children.length > 1 && ch.children[1].tagClass === "universal" && ch.children[1].tagNumber === asn1.TAGS.NULL) {
126
88
  throw E(prefix + "/bad-input", "a PBKDF2 prf equal to the default hmacWithSHA1 must be omitted (X.690 sec. 11.5)");
127
89
  }
@@ -131,28 +93,15 @@ function parsePbkdf2Params(paramsDer, opts, E, prefix, strictPrf) {
131
93
  return { salt: salt, iterations: iterations, prfNode: prfNode };
132
94
  }
133
95
 
134
- // AES-CBC content encryption / decryption (PKCS#7 pad). decrypt's final() throws on bad pad, and the caller
135
- // collapses that into its uniform decrypt-failed verdict.
136
- // cbcEncrypt(key, iv, plaintext, keyBits, E, code) -> the ciphertext.
137
- // Takes the caller's typed error for the same reason cbcDecrypt does: the cipher runs through the
138
- // shared guard, whose one throw has to keep the calling domain's own code.
139
96
  function cbcEncrypt(key, iv, plaintext, keyBits, E, code) {
140
97
  var c = nodeCrypto.createCipheriv("aes-" + keyBits + "-cbc", key, iv);
141
98
  return guard.secret.cipherFinish(c, plaintext, E, code, "a content-encryption intermediate");
142
99
  }
143
- // cbcDecrypt(key, iv, ct, keyBits, E, code) -> the recovered plaintext.
144
- // Takes the caller's typed error the way rc2.cbcDecrypt does, so a refusal keeps its own domain.
145
100
  function cbcDecrypt(key, iv, ct, keyBits, E, code) {
146
101
  var d = nodeCrypto.createDecipheriv("aes-" + keyBits + "-cbc", key, iv);
147
- // A wrong key fails inside final(), on the padding check, and update() has by then produced every
148
- // block but the last. Through the guard so that partial plaintext is cleared on both exits rather
149
- // than abandoned readable on exactly the path an attacker induces.
150
102
  return guard.secret.cipherFinish(d, ct, E, code, "the partially recovered plaintext");
151
103
  }
152
104
 
153
- // Higher-level PBES2 AES-CBC encrypt: derive an AES key from PRE-FORMATTED password bytes (the caller owns
154
- // the encoding -- CMS UTF-8 vs PKCS#12 App. B.1) and encrypt the plaintext, returning the PBES2
155
- // AlgorithmIdentifier + ciphertext. `cipherName` is an AES-CBC registry name (aes128/192/256-CBC).
156
105
  function pbes2Encrypt(pwBytes, plaintext, opts, E, prefix) {
157
106
  opts = opts || {};
158
107
  var cipherName = opts.cipher || "aes256-CBC";
@@ -163,33 +112,14 @@ function pbes2Encrypt(pwBytes, plaintext, opts, E, prefix) {
163
112
  var iterations = assertIterations(opts.iterations == null ? 2048 : opts.iterations, E, prefix);
164
113
  var salt = opts.salt != null ? assertSalt(opts.salt, E, prefix) : nodeCrypto.randomBytes(16);
165
114
  var iv = opts.iv != null ? opts.iv : nodeCrypto.randomBytes(16);
166
- // The derived key is this module's allocation and protects the caller's plaintext (a private key
167
- // in the pkcs8 and pkcs12 callers), so it is cleared once the encryption has consumed it. pwBytes
168
- // is not cleared: the caller formatted it and may still own the buffer.
169
115
  var key = nodeCrypto.pbkdf2Sync(pwBytes, salt, iterations, keyBits / 8, prfNode);
170
116
  try {
171
117
  return { algId: pbes2AlgId(salt, iterations, prf, cipherName, iv), ct: cbcEncrypt(key, iv, plaintext, keyBits, E, prefix + "/bad-input") };
172
118
  } finally {
173
- // E is the caller's error FACTORY, not a class; guard-secret delegates its only throw to
174
- // guard-bytes, which constructs. `new` on a factory yields the object the factory returns, so
175
- // the currency is compatible -- and the throw is unreachable here regardless, because a freshly
176
- // allocated pbkdf2 buffer cannot be detached.
177
119
  guard.secret.zeroize(key, E, prefix + "/bad-input", "the password-derived encryption key");
178
120
  }
179
121
  }
180
122
 
181
- // PBES2 AES-CBC DECRYPT: parse the PBES2 params (PBKDF2 kdf + AES-CBC scheme), derive the key from
182
- // PRE-FORMATTED password bytes (the caller owns UTF-8 vs BMPString), and AES-CBC-decrypt. Structural faults
183
- // (a non-PBKDF2 KDF, a non-AES-CBC scheme, an over-cap salt/iteration, a wrong-length IV, a malformed param
184
- // SEQUENCE) are typed pre-derivation and password-independent, so they leak no oracle; the generic
185
- // <prefix>/bad-input a param guard raises is normalized to the structural <prefix>/bad-algorithm-parameters.
186
- // A wrong key / bad PKCS#7 pad collapses to the UNIFORM <prefix>/decrypt-failed (RFC 8018 sec. 8). The
187
- // plaintext integrity re-check (re-parse as a PrivateKeyInfo / SafeContents) is the CALLER's step.
188
- // `budget` (optional) is a shared { rounds } tally a caller decrypting MANY structures under one
189
- // call charges against, so the per-structure iteration cap cannot simply reset each time: PBKDF2
190
- // runs on the event loop, and a store that repeats a costly bag up to the parser's element limit
191
- // otherwise multiplies the cap by that limit. A caller decrypting exactly one structure passes
192
- // nothing and is bounded by the cap alone.
193
123
  function pbes2Decrypt(pwBytes, params, ciphertext, opts, E, prefix, budget) {
194
124
  var keyBits, iv, pb;
195
125
  try {
@@ -197,7 +127,7 @@ function pbes2Decrypt(pwBytes, params, ciphertext, opts, E, prefix, budget) {
197
127
  var kdf = requireChildren(p[0], 2, "PBES2 keyDerivationFunc", E, prefix);
198
128
  var encScheme = requireChildren(p[1], 2, "PBES2 encryptionScheme", E, prefix);
199
129
  if (asn1.read.oid(kdf[0]) !== O("pbkdf2")) throw E(prefix + "/unsupported-algorithm", "the PBES2 keyDerivationFunc must be PBKDF2 (RFC 8018 sec. 6.2)");
200
- pb = parsePbkdf2Params(kdf[1].bytes, opts, E, prefix, true); // strictPrf: reject a non-canonical explicit default prf
130
+ pb = parsePbkdf2Params(kdf[1].bytes, opts, E, prefix, true);
201
131
  var encOid = asn1.read.oid(encScheme[0]);
202
132
  keyBits = CONTENT_KEYBITS[encOid];
203
133
  if (!keyBits || (oid.name(encOid) || "").indexOf("CBC") === -1) throw E(prefix + "/unsupported-algorithm", "unsupported PBES2 encryptionScheme " + (oid.name(encOid) || encOid) + " (AES-CBC only)");
@@ -210,7 +140,6 @@ function pbes2Decrypt(pwBytes, params, ciphertext, opts, E, prefix, budget) {
210
140
  }
211
141
  throw E(prefix + "/bad-algorithm-parameters", "malformed PBES2 parameters", e);
212
142
  }
213
- // Charge the shared budget before deriving, so the work is refused instead of performed.
214
143
  if (budget) {
215
144
  budget.rounds -= pb.iterations;
216
145
  if (budget.rounds < 0) throw E(prefix + "/iteration-limit", "the aggregate PBKDF2 key-derivation work exceeds the budget (a hostile many-element input)");
@@ -221,13 +150,8 @@ function pbes2Decrypt(pwBytes, params, ciphertext, opts, E, prefix, budget) {
221
150
  finally { guard.secret.zeroize(dk, E, prefix + "/bad-input", "the password-derived decryption key"); }
222
151
  }
223
152
 
224
- // ---- PBMAC1 (RFC 9579 / RFC 8018 App. A.5) : PBKDF2 -> HMAC over a message --
225
- // An hmacWithSHA_n AlgorithmIdentifier carries NULL parameters (RFC 8018 B.1.1).
226
153
  function _hmacAlgId(name) { return b.sequence([b.oid(O(name)), b.nullValue()]); }
227
154
 
228
- // The id-PBMAC1 AlgorithmIdentifier: id-PBMAC1 + PBMAC1-params { keyDerivationFunc PBKDF2, messageAuthScheme
229
- // HMAC }, the byte-exact inverse of schema-pkcs12 / schema-cmp's PBMAC1_PARAMS. `desc` = { salt,
230
- // iterationCount, keyLength, prfName, macName }. The prf is omitted iff it equals the default hmacWithSHA1.
231
155
  function pbmac1AlgId(desc) {
232
156
  var pbkdf2Params = [b.octetString(desc.salt), b.integer(BigInt(desc.iterationCount)), b.integer(BigInt(desc.keyLength))];
233
157
  if (desc.prfName !== "hmacWithSHA1") pbkdf2Params.push(_hmacAlgId(desc.prfName));
@@ -235,26 +159,15 @@ function pbmac1AlgId(desc) {
235
159
  return b.sequence([b.oid(O("pbmac1")), b.sequence([pbkdf2AlgId, _hmacAlgId(desc.macName)])]);
236
160
  }
237
161
 
238
- // Compute PBMAC1 = HMAC_macHash(PBKDF2(pwBytes, salt, iter, keyLength, prfHash), message). The PBKDF2 prf
239
- // and the HMAC messageAuthScheme are INDEPENDENT (RFC 9579 sec. 4 / RFC 8018 App. A.5) -- e.g. a SHA-512 PRF
240
- // with a SHA-256 HMAC -- so both are passed explicitly. `prfHash` / `macHash` are WebCrypto hash names
241
- // ("SHA-256"); pwBytes is pre-formatted (the caller owns the encoding).
242
162
  function pbmac1(pwBytes, salt, iterationCount, keyLength, prfHash, macHash, message) {
243
163
  var subtle = webcrypto.webcrypto.subtle;
244
164
  return subtle.importKey("raw", pwBytes, { name: "PBKDF2" }, false, ["deriveBits"]).then(function (baseKey) {
245
165
  return subtle.deriveBits({ name: "PBKDF2", salt: salt, iterations: iterationCount, hash: prfHash }, baseKey, keyLength * 8);
246
166
  }).then(function (bits) {
247
- // The derived MAC key is this function's allocation, in two forms: the ArrayBuffer deriveBits
248
- // returned and the Buffer view over it that is imported. Clearing the view clears both, and it
249
- // runs whether the signing succeeds or throws. The sibling PBES2 encrypt/decrypt above clear
250
- // their derived keys, and every PBMAC1 consumer (PKCS#12 build and verification) inherits this.
251
167
  var mk = Buffer.from(bits);
252
168
  return subtle.importKey("raw", mk, { name: "HMAC", hash: macHash }, false, ["sign"]).then(function (hmacKey) {
253
169
  return subtle.sign({ name: "HMAC" }, hmacKey, message);
254
170
  }).finally(function () {
255
- // pbmac1 takes no caller error factory, and this key is engine-adjacent, so the engine's
256
- // typed class is the right currency -- a raw TypeError must never escape a lib boundary.
257
- // Unreachable in practice: a freshly allocated Buffer cannot be detached.
258
171
  guard.secret.zeroize(mk, webcrypto.WebCryptoError, "webcrypto/operation", "the PBMAC1 key");
259
172
  });
260
173
  }).then(function (sig) { return Buffer.from(sig); });