@blamejs/pki 0.6.13 → 0.6.15

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 (114) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +1 -1
  3. package/index.js +1 -1
  4. package/lib/acme.js +59 -815
  5. package/lib/asn1-der.js +7 -245
  6. package/lib/attrcert-sign.js +12 -260
  7. package/lib/attrcert-verify.js +1 -7
  8. package/lib/byte-reader.js +0 -8
  9. package/lib/byte-writer.js +0 -11
  10. package/lib/cbor-det.js +0 -54
  11. package/lib/cmc-build.js +15 -357
  12. package/lib/cmc-verify.js +6 -239
  13. package/lib/cmp-build.js +41 -317
  14. package/lib/cmp-session.js +73 -760
  15. package/lib/cmp-verify.js +32 -488
  16. package/lib/cms-compress.js +3 -32
  17. package/lib/cms-decrypt.js +29 -294
  18. package/lib/cms-encrypt.js +14 -234
  19. package/lib/cms-sign.js +29 -324
  20. package/lib/cms-verify.js +9 -500
  21. package/lib/composite-kem.js +2 -102
  22. package/lib/composite-sig.js +1 -77
  23. package/lib/constants.js +0 -249
  24. package/lib/crl-sign.js +9 -237
  25. package/lib/crl-verify.js +1 -10
  26. package/lib/crmf-sign.js +19 -198
  27. package/lib/crmf-verify.js +1 -12
  28. package/lib/csr-sign.js +3 -34
  29. package/lib/csr-verify.js +1 -12
  30. package/lib/ct.js +28 -253
  31. package/lib/edwards-point.js +10 -44
  32. package/lib/est.js +28 -764
  33. package/lib/framework-error.js +4 -182
  34. package/lib/guard-all.js +1 -58
  35. package/lib/guard-async.js +1 -36
  36. package/lib/guard-bytes.js +6 -650
  37. package/lib/guard-compress.js +5 -102
  38. package/lib/guard-crypto.js +1 -40
  39. package/lib/guard-der.js +2 -93
  40. package/lib/guard-encoding.js +2 -60
  41. package/lib/guard-header.js +1 -36
  42. package/lib/guard-identifier.js +7 -531
  43. package/lib/guard-intrinsic.js +1 -150
  44. package/lib/guard-json.js +10 -73
  45. package/lib/guard-limits.js +1 -77
  46. package/lib/guard-list.js +1 -49
  47. package/lib/guard-name.js +3 -209
  48. package/lib/guard-parsed.js +7 -335
  49. package/lib/guard-range.js +1 -71
  50. package/lib/guard-secret.js +1 -102
  51. package/lib/guard-text.js +1 -64
  52. package/lib/guard-time.js +1 -97
  53. package/lib/hpke.js +3 -105
  54. package/lib/http-digest.js +14 -142
  55. package/lib/http-retry-after.js +1 -47
  56. package/lib/http-transport.js +21 -131
  57. package/lib/inspect.js +30 -284
  58. package/lib/ip-utils.js +6 -47
  59. package/lib/jose.js +7 -142
  60. package/lib/key.js +2 -67
  61. package/lib/lint.js +9 -194
  62. package/lib/merkle.js +1 -27
  63. package/lib/mime.js +9 -82
  64. package/lib/ocsp-request-verify.js +1 -14
  65. package/lib/ocsp-verify.js +1 -82
  66. package/lib/ocsp.js +11 -169
  67. package/lib/oid.js +5 -337
  68. package/lib/path-validate.js +103 -1492
  69. package/lib/pbes2.js +2 -89
  70. package/lib/pkcs12-build.js +31 -379
  71. package/lib/pki-build.js +64 -290
  72. package/lib/rc2.js +2 -18
  73. package/lib/rfc3339.js +4 -27
  74. package/lib/scep.js +59 -233
  75. package/lib/schema-all.js +0 -122
  76. package/lib/schema-attrcert.js +4 -146
  77. package/lib/schema-c509.js +153 -802
  78. package/lib/schema-cmc.js +5 -220
  79. package/lib/schema-cmp.js +2 -223
  80. package/lib/schema-cms.js +13 -427
  81. package/lib/schema-crl.js +5 -68
  82. package/lib/schema-crmf.js +6 -167
  83. package/lib/schema-csr.js +1 -54
  84. package/lib/schema-csrattrs.js +2 -87
  85. package/lib/schema-engine.js +0 -152
  86. package/lib/schema-ocsp.js +0 -117
  87. package/lib/schema-pkcs12.js +2 -93
  88. package/lib/schema-pkcs8.js +3 -35
  89. package/lib/schema-pkix.js +24 -655
  90. package/lib/schema-smime.js +0 -54
  91. package/lib/schema-tsp.js +3 -99
  92. package/lib/schema-x509.js +4 -63
  93. package/lib/shbs.js +11 -95
  94. package/lib/sign-scheme.js +2 -97
  95. package/lib/sigstore.js +9 -169
  96. package/lib/sleep.js +2 -8
  97. package/lib/smime.js +15 -408
  98. package/lib/tls-cert-compress.js +0 -62
  99. package/lib/trust.js +19 -185
  100. package/lib/tsp-sign.js +16 -270
  101. package/lib/validator-all.js +1 -30
  102. package/lib/validator-attcert.js +2 -46
  103. package/lib/validator-cose.js +2 -153
  104. package/lib/validator-keydesc.js +1 -37
  105. package/lib/validator-sig.js +1 -46
  106. package/lib/validator-tls.js +1 -88
  107. package/lib/validator-tpm.js +19 -122
  108. package/lib/verify-seam.js +1 -24
  109. package/lib/webauthn-mds.js +3 -400
  110. package/lib/webauthn.js +12 -833
  111. package/lib/webcrypto.js +5 -485
  112. package/lib/x509-sign.js +4 -108
  113. package/package.json +1 -1
  114. package/sbom.cdx.json +6 -6
package/lib/hpke.js CHANGED
@@ -28,14 +28,11 @@ var nodeCrypto = require("crypto");
28
28
  var frameworkError = require("./framework-error");
29
29
  var guard = require("./guard-all");
30
30
  var intrinsic = require("./guard-intrinsic");
31
- // Own-key membership through an operation taken at load. Written out, the question reads two
32
- // replaceable properties to answer one thing, and here it decides which suite parameters are read.
33
31
  var _hasOwn = intrinsic.hasOwn;
34
32
 
35
33
  var HpkeError = frameworkError.HpkeError;
36
34
  function _err(code, message, cause) { return new HpkeError(code, message, cause); }
37
35
 
38
- // ---- I2OSP + byte helpers ----------------------------------------------------
39
36
 
40
37
  function i2osp(n, len) {
41
38
  var b = Buffer.alloc(len);
@@ -49,28 +46,17 @@ function xor(a, b) { var o = Buffer.alloc(a.length); for (var i = 0; i < a.lengt
49
46
  var HPKE_V1 = Buffer.from("HPKE-v1", "ascii");
50
47
  function L(s) { return Buffer.from(s, "ascii"); }
51
48
 
52
- // ---- registries: the RFC 9180 sec. 7 data tables (Tables 2/3/5) --------------
53
49
 
54
- // KDF: id -> { hash (node name), Nh }.
55
- // HKDF-SHA384 (0x0002) and DHKEM(P-384) (0x0011) are registered by RFC 9180 sec.
56
- // 7 but Appendix A / the cited [TestVectors] file ship no known-answer vector for
57
- // them, so they are omitted here until an authoritative KAT exists. A request for
58
- // either fails closed as hpke/unknown-suite, because no test vector proves the
59
- // crypto it would otherwise run. They admit as a one-row addition the moment a
60
- // KAT lands.
61
50
  var KDFS = {
62
51
  0x0001: { hash: "sha256", Nh: 32 },
63
52
  0x0003: { hash: "sha512", Nh: 64 },
64
53
  };
65
- // AEAD: id -> { cipher (node name), Nk, Nn, Nt } or exportOnly.
66
54
  var AEADS = {
67
55
  0x0001: { cipher: "aes-128-gcm", Nk: 16, Nn: 12, Nt: 16 },
68
56
  0x0002: { cipher: "aes-256-gcm", Nk: 32, Nn: 12, Nt: 16 },
69
57
  0x0003: { cipher: "chacha20-poly1305", Nk: 32, Nn: 12, Nt: 16 },
70
58
  0xFFFF: { exportOnly: true, Nn: 12 },
71
59
  };
72
- // KEM: id -> DHKEM group descriptor. `group` is the node keygen/import family;
73
- // `kdf` is the KEM-internal KDF (its ExtractAndExpand); Nsecret = that KDF's Nh.
74
60
  var KEMS = {
75
61
  0x0010: { kind: "ec", curve: "P-256", nodeCurve: "prime256v1", kdf: 0x0001, Nsecret: 32, Npub: 65 },
76
62
  0x0012: { kind: "ec", curve: "P-521", nodeCurve: "secp521r1", kdf: 0x0003, Nsecret: 64, Npub: 133 },
@@ -80,17 +66,11 @@ var KEMS = {
80
66
 
81
67
  var MODE_BASE = 0x00, MODE_PSK = 0x01, MODE_AUTH = 0x02, MODE_AUTH_PSK = 0x03;
82
68
 
83
- // Format a code point for an error message without assuming it is a number: a
84
- // missing suiteIds member arrives as undefined, and undefined.toString(16) would
85
- // crash the very error path meant to report it.
86
69
  function _idStr(id) { return typeof id === "number" ? "0x" + id.toString(16) : String(id); }
87
70
  function _kem(id) { var s = KEMS[id]; if (!s) throw _err("hpke/unknown-suite", "unsupported KEM id " + _idStr(id)); return s; }
88
71
  function _kdf(id) { var s = KDFS[id]; if (!s) throw _err("hpke/unknown-suite", "unsupported KDF id " + _idStr(id)); return s; }
89
72
  function _aead(id) { var s = AEADS[id]; if (!s) throw _err("hpke/unknown-suite", "unsupported AEAD id " + _idStr(id)); return s; }
90
73
 
91
- // ---- labeled KDF (RFC 9180 sec. 4): HKDF Extract/Expand SPLIT over HMAC -------
92
- // suite_id is the caller's ("KEM"||... for the KEM layer, "HPKE"||... for the
93
- // rest). Extract = HMAC(salt-or-zeros, ikm); Expand = RFC 5869 sec. 2.3 feedback.
94
74
 
95
75
  function _extract(hash, Nh, salt, ikm) {
96
76
  var key = (salt && salt.length) ? salt : Buffer.alloc(Nh);
@@ -100,16 +80,11 @@ function _expand(hash, Nh, prk, info, len) {
100
80
  if (len > 255 * Nh) throw _err("hpke/export-length", "requested length " + len + " exceeds 255*Nh");
101
81
  var out = [], t = Buffer.alloc(0), n = Math.ceil(len / Nh);
102
82
  for (var i = 1; i <= n; i++) {
103
- // The feedback input carries the PREVIOUS output block, so each round's concatenation holds
104
- // secret material and is cleared once the HMAC has absorbed it.
105
83
  var fed = concat([t, info, Buffer.from([i])]);
106
84
  t = nodeCrypto.createHmac(hash, prk).update(fed).digest();
107
85
  guard.secret.zeroize(fed, HpkeError, "hpke/bad-input", "an expand feedback input");
108
86
  out.push(t);
109
87
  }
110
- // An exact-sized owning buffer, not a VIEW over the joined blocks: this is keying material, and a
111
- // caller clearing what it received must not leave the unused tail of the final HMAC block behind
112
- // it. The accumulator and each block are cleared here.
113
88
  var joined = concat(out);
114
89
  var exact = Buffer.alloc(len);
115
90
  joined.copy(exact, 0, 0, len);
@@ -118,8 +93,6 @@ function _expand(hash, Nh, prk, info, len) {
118
93
  return exact;
119
94
  }
120
95
  function _labeledExtract(kdf, suiteId, salt, label, ikm) {
121
- // The concatenation copies the input keying material (a DH secret or a PSK) into a fresh
122
- // buffer, so that copy is cleared once extract has consumed it. The caller still owns .
123
96
  var labeled = concat([HPKE_V1, suiteId, L(label), ikm]);
124
97
  try { return _extract(kdf.hash, kdf.Nh, salt, labeled); }
125
98
  finally { guard.secret.zeroize(labeled, HpkeError, "hpke/bad-input", "the labeled extract input"); }
@@ -128,14 +101,10 @@ function _labeledExpand(kdf, suiteId, prk, label, info, len) {
128
101
  return _expand(kdf.hash, kdf.Nh, prk, concat([i2osp(len, 2), HPKE_V1, suiteId, L(label), info]), len);
129
102
  }
130
103
 
131
- // ---- KEM key (de)serialization + Diffie-Hellman (node:crypto) ----------------
132
104
 
133
105
  var OKP_SPKI = { X25519: "302a300506032b656e032100", X448: "3042300506032b656f033900" };
134
106
  var OKP_PKCS8 = { X25519: "302e020100300506032b656e04220420", X448: "3046020100300506032b656f043a0438" };
135
107
 
136
- // Deserialize a serialized KEM public key (enc / pkRm / pkSm) into a node
137
- // KeyObject. EC is an uncompressed 0x04 point (SerializePublicKey, sec. 7.1.1);
138
- // OKP is the raw curve point. A wrong length / shape fails closed.
139
108
  function _importPublic(kem, raw) {
140
109
  if (!Buffer.isBuffer(raw) || raw.length !== kem.Npub) {
141
110
  throw _err("hpke/bad-key", kem.curve + " public key must be " + kem.Npub + " bytes");
@@ -153,18 +122,13 @@ function _importPublic(kem, raw) {
153
122
  throw _err("hpke/bad-key", "invalid " + kem.curve + " public key", e);
154
123
  }
155
124
  }
156
- // Serialize a node public KeyObject back to the RFC 9180 wire encoding.
157
125
  function _exportPublic(kem, keyObject) {
158
126
  var jwk = keyObject.export({ format: "jwk" });
159
127
  if (kem.kind === "ec") return concat([Buffer.from([0x04]), _b64u(jwk.x), _b64u(jwk.y)]);
160
128
  return _b64u(jwk.x);
161
129
  }
162
- // Node's own JWK export -- decode its canonical base64url coordinates through the
163
- // guard so the alphabet/canonicality check is the single shared choke point.
164
130
  function _b64u(s) { return guard.encoding.base64url(s, null, _err, "hpke/bad-key", "JWK coordinate"); }
165
131
 
166
- // Import a serialized KEM private key (skRm / skEm / skSm) into a node KeyObject,
167
- // given the matching serialized public key for the EC JWK (or none for OKP).
168
132
  function _importPrivate(kem, rawSk, rawPk) {
169
133
  try {
170
134
  if (kem.kind === "ec") {
@@ -177,11 +141,6 @@ function _importPrivate(kem, rawSk, rawPk) {
177
141
  throw _err("hpke/bad-key", "invalid " + kem.curve + " private key", e);
178
142
  }
179
143
  }
180
- // The single KEM Diffie-Hellman choke point. node:crypto throws a raw
181
- // ERR_OSSL_FAILED_DURING_DERIVATION when the peer point is low-order / invalid
182
- // (an all-zero X25519 shared secret, a point not on the curve). RFC 9180 sec.
183
- // 4.1: Decap raises an error on DH failure. Surface it as a typed hpke/bad-key
184
- // so no raw OpenSSL error escapes any encap / decap path.
185
144
  function _dh(privateKey, publicKey) {
186
145
  try {
187
146
  return nodeCrypto.diffieHellman({ privateKey: privateKey, publicKey: publicKey });
@@ -194,34 +153,22 @@ function _generate(kem) {
194
153
  return nodeCrypto.generateKeyPairSync(kem.curve.toLowerCase());
195
154
  }
196
155
 
197
- // ---- DHKEM (RFC 9180 sec. 4.1) -----------------------------------------------
198
156
 
199
157
  function _kemSuiteId(kemId) { return concat([L("KEM"), i2osp(kemId, 2)]); }
200
158
  function _extractAndExpand(kem, dh, kemContext) {
201
159
  var kdf = _kdf(kem.kdf), sid = _kemSuiteId(_kemId(kem));
202
- // The extract PRK is a secret intermediate this function allocated: it is as sensitive as the DH
203
- // input it summarises, so it is cleared once the expand has consumed it.
204
160
  var eaePrk = _labeledExtract(kdf, sid, Buffer.alloc(0), "eae_prk", dh);
205
161
  try { return _labeledExpand(kdf, sid, eaePrk, "shared_secret", kemContext, kem.Nsecret); }
206
162
  finally { guard.secret.zeroize(eaePrk, HpkeError, "hpke/bad-input", "the KEM extract PRK"); }
207
163
  }
208
164
  function _kemId(kem) { for (var k in KEMS) if (KEMS[k] === kem) return Number(k); return 0; }
209
165
 
210
- // Encap(pkR) -> { sharedSecret, enc }. An injected ephemeral (skE, pkEnc) makes
211
- // the KAT deterministic; otherwise a fresh ephemeral is generated.
212
166
  function _ephemeral(kem, eph) {
213
167
  if (eph) return { skE: _importPrivate(kem, eph.skm, eph.pkm), enc: _buf(eph.pkm) };
214
168
  var kp = _generate(kem);
215
169
  return { skE: kp.privateKey, enc: _exportPublic(kem, kp.publicKey) };
216
170
  }
217
- // The raw DH output is the KEM's shared secret before extraction: it is this module's allocation
218
- // and is cleared once _extractAndExpand has consumed it, on every DHKEM arm. In the authenticated
219
- // arms builds a THIRD copy holding both DH results, so the concatenation is cleared as
220
- // well, since clearing only the pieces would leave the joined buffer readable.
221
171
  function _wipeDh(dh) { guard.secret.zeroize(dh, HpkeError, "hpke/bad-input", "the KEM shared secret"); }
222
- // Every agreement happens inside the protected region. In the authenticated modes the second
223
- // agreement can throw on an attacker-supplied low-order sender key, and a first secret computed
224
- // outside the region would be left behind on exactly that failure path.
225
172
  function _encap(kem, pkR, pkRm, eph) {
226
173
  var e = _ephemeral(kem, eph);
227
174
  var dh = null;
@@ -259,7 +206,6 @@ function _authDecap(kem, enc, skR, pkRm, pkS, pkSm) {
259
206
  } finally { _wipeDh(dh1); _wipeDh(dh2); _wipeDh(dh); }
260
207
  }
261
208
 
262
- // ---- key schedule (RFC 9180 sec. 5.1) ----------------------------------------
263
209
 
264
210
  function _hpkeSuiteId(kemId, kdfId, aeadId) { return concat([L("HPKE"), i2osp(kemId, 2), i2osp(kdfId, 2), i2osp(aeadId, 2)]); }
265
211
 
@@ -276,8 +222,6 @@ function _keySchedule(suite, mode, sharedSecret, info, psk, pskId, role) {
276
222
  var pskIdHash = _labeledExtract(kdf, sid, Buffer.alloc(0), "psk_id_hash", pskId);
277
223
  var infoHash = _labeledExtract(kdf, sid, Buffer.alloc(0), "info_hash", info);
278
224
  var ksc = concat([Buffer.from([mode]), pskIdHash, infoHash]);
279
- // is the key schedule's master PRK -- every key below is derived from it, so it is the
280
- // most valuable intermediate here and is cleared once the derivations are done.
281
225
  var secret = _labeledExtract(kdf, sid, sharedSecret, "secret", psk);
282
226
  try {
283
227
  var exporterSecret = _labeledExpand(kdf, sid, secret, "exp", ksc, kdf.Nh);
@@ -292,18 +236,11 @@ function _keySchedule(suite, mode, sharedSecret, info, psk, pskId, role) {
292
236
  }
293
237
  }
294
238
 
295
- // ---- AEAD context (RFC 9180 sec. 5.2 / 5.3) ----------------------------------
296
239
 
297
- // role is "S" (sender: seal only) or "R" (recipient: open only). Sender and
298
- // recipient derive the same key + base_nonce, so a wrong-direction call would
299
- // reuse a nonce (RFC 9180 sec. 5.2); export is available to both.
300
240
  function Context(suite, key, baseNonce, exporterSecret, role) {
301
241
  this._suite = suite; this._key = key; this._baseNonce = baseNonce;
302
242
  this._exporterSecret = exporterSecret; this._seq = 0n; this._role = role;
303
243
  }
304
- // Clear the context's key material. The single-shot entry points below build a context, use it once
305
- // and drop it, so without this the AEAD key, base nonce and exporter secret stay readable for the
306
- // process lifetime -- the multi-message API hands the context to the caller, who owns its lifetime.
307
244
  Context.prototype._dispose = function () {
308
245
  guard.secret.zeroizeAll([this._key, this._baseNonce, this._exporterSecret], HpkeError, "hpke/bad-input", "the HPKE context key material");
309
246
  };
@@ -340,9 +277,6 @@ Context.prototype.open = function (aad, ct) {
340
277
  if (aad && aad.length) d.setAAD(aad);
341
278
  d.setAuthTag(ct.subarray(ct.length - aead.Nt));
342
279
  var pt;
343
- // Through the shared guard so the recovered plaintext is destroyed when the AEAD tag does not
344
- // check out (RFC 9180 sec. 5.2 gives open one outcome on failure, and it is not a copy left in
345
- // the heap), and so the success path's abandoned intermediate is cleared too.
346
280
  try { pt = guard.secret.cipherFinish(d, ct.subarray(0, ct.length - aead.Nt), HpkeError, "hpke/bad-input", "the recovered plaintext"); }
347
281
  catch (e) { throw _err("hpke/open-failed", "AEAD authentication failed (RFC 9180 sec. 5.2)", e); }
348
282
  this._inc();
@@ -354,7 +288,6 @@ Context.prototype.export = function (exporterContext, len) {
354
288
  };
355
289
  function _buf(x) { return Buffer.isBuffer(x) ? x : Buffer.from(x || []); }
356
290
 
357
- // ---- suite resolution + setup ------------------------------------------------
358
291
 
359
292
  function _suite(ids) {
360
293
  if (!ids || typeof ids !== "object") throw _err("hpke/unknown-suite", "suiteIds must be an object { kem, kdf, aead } from pki.hpke.suites");
@@ -363,14 +296,9 @@ function _suite(ids) {
363
296
  return { kem: kem, kdf: kdf, aead: aead, kemId: kemId, kdfId: kdfId, aeadId: aeadId, suiteId: _hpkeSuiteId(kemId, kdfId, aeadId) };
364
297
  }
365
298
 
366
- // A KEM key argument is a node KeyObject or serialized bytes: a public key as a
367
- // raw buffer (or { pkm }), a private key as { skm, pkm } (raw scalar + public
368
- // point). A KAT drives the deterministic path via those serialized forms.
369
299
  function _recipPublic(suite, pk) {
370
300
  if (Buffer.isBuffer(pk)) return { key: _importPublic(suite.kem, pk), pkm: pk };
371
301
  if (pk && pk.pkm) return { key: _importPublic(suite.kem, pk.pkm), pkm: pk.pkm };
372
- // A node KeyObject: derive its wire form. A null/undefined/invalid value must
373
- // fail closed here, so no raw error from node's export escapes upward.
374
302
  try {
375
303
  return { key: pk, pkm: _exportPublic(suite.kem, pk) };
376
304
  } catch (e) {
@@ -380,10 +308,6 @@ function _recipPublic(suite, pk) {
380
308
  }
381
309
  function _recipPrivate(suite, sk) {
382
310
  if (sk && sk.skm) return { key: _importPrivate(suite.kem, sk.skm, sk.pkm), pkm: sk.pkm };
383
- // A raw scalar alone cannot be imported (an EC private key needs its public
384
- // point for the JWK), so the serialized private form is { skm, pkm }; reject a
385
- // bare buffer, and fail any other bad key closed; a raw createPublicKey error
386
- // must not escape the setup path.
387
311
  if (Buffer.isBuffer(sk)) throw _err("hpke/bad-key", "a serialized private key must be provided as { skm, pkm } (raw scalar + public point), not a bare buffer");
388
312
  try {
389
313
  var pkm = _exportPublic(suite.kem, nodeCrypto.createPublicKey(sk));
@@ -394,21 +318,6 @@ function _recipPrivate(suite, sk) {
394
318
  }
395
319
  }
396
320
 
397
- // Resolve and validate the HPKE mode: RFC 9180 sec. 5.1 defines exactly base /
398
- // psk / auth / auth-psk. An unknown mode must fail closed, never key-schedule
399
- // with an out-of-registry mode byte.
400
- // The sender and the recipient read the same option object from OPPOSITE ends, so each direction
401
- // gets its own table. A shared union recognizes every name at both ends and so accepts the one that
402
- // cannot do anything there: `senderPublicKey` handed to setupS, or
403
- // `senderKey` handed to setupR, is silently ignored, which is the exact silence these tables exist
404
- // to remove, in a wider form. An option that means nothing where it was passed is a misunderstanding
405
- // worth reporting, and usually a misdirected auth-mode setup.
406
- //
407
- // Every one of these narrows or authenticates: a misspelled `psk` leaves a psk-mode setup with no
408
- // pre-shared key and a misspelled `senderKey` leaves an auth-mode setup unauthenticated, each
409
- // failing with a message about the field the caller believes they supplied. `eph` is the
410
- // deterministic-KAT seam and is sender-side only; supplied by mistake it fixes the ephemeral key,
411
- // which is the one option here whose silent acceptance is catastrophic.
412
321
  var _COMMON_KEYS = { mode: 1, info: 1, psk: 1, pskId: 1 };
413
322
  function _withCommon(extra) {
414
323
  var out = {};
@@ -417,11 +326,11 @@ function _withCommon(extra) {
417
326
  return out;
418
327
  }
419
328
  var _SETUP_S_KEYS = _withCommon({
420
- senderKey: 1, // auth modes: the sender's OWN KEM private key
421
- eph: 1, // test-vector determinism: fixes the ephemeral key this side generates
329
+ senderKey: 1,
330
+ eph: 1,
422
331
  });
423
332
  var _SETUP_R_KEYS = _withCommon({
424
- senderPublicKey: 1, // auth modes: the sender's KEM public key, to authenticate them
333
+ senderPublicKey: 1,
425
334
  });
426
335
  function _mode(opts, keys, who) {
427
336
  guard.identifier.assertKnownKeys(opts, keys, _err, "hpke/bad-input", function (k) {
@@ -438,8 +347,6 @@ function _mode(opts, keys, who) {
438
347
  return mode;
439
348
  }
440
349
 
441
- // pki.hpke.suites -- the RFC 9180 sec. 7 registry code points (KEM / KDF / AEAD /
442
- // MODE), passed to the setup functions to select a ciphersuite (documented in the
443
350
  // @module @intro; a data registry, not a callable primitive).
444
351
  var suites = {
445
352
  KEM: { DHKEM_P256_HKDF_SHA256: 0x0010, DHKEM_P521_HKDF_SHA512: 0x0012, DHKEM_X25519_HKDF_SHA256: 0x0020, DHKEM_X448_HKDF_SHA512: 0x0021 },
@@ -448,8 +355,6 @@ var suites = {
448
355
  MODE: { BASE: MODE_BASE, PSK: MODE_PSK, AUTH: MODE_AUTH, AUTH_PSK: MODE_AUTH_PSK },
449
356
  };
450
357
 
451
- // setup*S(suiteIds, pkR, opts) -> { enc, context }. opts: { info, psk, pskId,
452
- // senderKey (auth), eph (KAT determinism) }. setup*R(suiteIds, enc, skR, opts).
453
358
 
454
359
  /**
455
360
  * @primitive pki.hpke.setupS
@@ -528,8 +433,6 @@ function _setupR(ids, enc, skR, opts) {
528
433
  } else {
529
434
  ss = _decap(kem, _buf(enc), r.key, r.pkm);
530
435
  }
531
- // The recipient derives this shared secret and never hands it back (unlike setupS, whose caller
532
- // receives it and owns it from then on), so it is cleared once the key schedule has consumed it.
533
436
  try { return _keySchedule(suite, mode, ss, _buf(opts.info), _buf(opts.psk), _buf(opts.pskId), "R"); }
534
437
  finally { guard.secret.zeroize(ss, HpkeError, "hpke/bad-input", "the KEM shared secret"); }
535
438
  }
@@ -553,14 +456,9 @@ function _setupR(ids, enc, skR, opts) {
553
456
  * var out = pki.hpke.seal(ids, pkR, {}, Buffer.from("aad"), Buffer.from("msg"));
554
457
  */
555
458
  function seal(ids, pkR, opts, aad, pt) {
556
- // _setupS itself can reject after allocating (an unusable AEAD, a bad psk pairing), so the whole
557
- // call is inside the protected region rather than only what follows a successful setup.
558
459
  var s = null;
559
460
  try {
560
461
  s = _setupS(ids, pkR, opts);
561
- // The single-shot wrapper returns neither the setup result nor its shared secret, so no caller can
562
- // own that buffer -- it is cleared here along with the context. setupS itself still hands both to
563
- // its caller, whose lifetime they become.
564
462
  return { enc: s.enc, ct: s.context.seal(_buf(aad), _buf(pt)) };
565
463
  } finally {
566
464
  if (s) {