@leofcoin/chain 1.10.14 → 1.10.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 (39) hide show
  1. package/exports/browser/beacon-envelope.js +1 -1
  2. package/exports/browser/beacon-epoch.js +1 -1
  3. package/exports/browser/beacon-lifecycle.js +1 -1
  4. package/exports/browser/beacon-round.js +1 -1
  5. package/exports/browser/beacon-wire.js +2 -2
  6. package/exports/browser/beacon.js +1 -1
  7. package/exports/browser/{browser-DvU1xNFS-BJCQsckZ.js → browser-DvU1xNFS-DmmNUdE-.js} +3 -3
  8. package/exports/browser/{browser-crypto-Yk_e6OHw.js → browser-crypto-B9N9KlL4.js} +1 -1
  9. package/exports/browser/chain.js +3 -3
  10. package/exports/browser/{client-DDC8C510-CUi3_3uT.js → client-DDC8C510-3uaB70KL.js} +4 -4
  11. package/exports/browser/{connection-monitor-BjXI0nBP.js → connection-monitor-GPztgSSJ.js} +2 -1
  12. package/exports/browser/{index-Bxr5Iztg-AmkW0EHS.js → index-Bxr5Iztg-WbFIosyf.js} +3 -3
  13. package/exports/browser/{index-C_RakUAS.js → index-Ccn5sExe.js} +1 -1
  14. package/exports/browser/{messages-DH0tgNM9-CZwrcL37.js → messages-DH0tgNM9-C2CtyLsf.js} +3 -3
  15. package/exports/browser/{node-browser-CQugE1WZ.js → node-browser-BYi7D_oa.js} +5 -5
  16. package/exports/browser/node-browser.js +3 -3
  17. package/exports/browser/workers/machine-worker.js +16 -4
  18. package/exports/node.js +5 -0
  19. package/exports/workers/machine-worker.js +16 -4
  20. package/package.json +5 -1
  21. package/exports/browser/browser-DvU1xNFS-4-PGqr4c.js +0 -151
  22. package/exports/browser/browser-DvU1xNFS-D9eSzJGJ.js +0 -151
  23. package/exports/browser/browser-crypto-BHeOz9rj.js +0 -8893
  24. package/exports/browser/browser-crypto-CTP3Yk4M.js +0 -8893
  25. package/exports/browser/client-DDC8C510-DbIdQjhy.js +0 -2225
  26. package/exports/browser/client-DDC8C510-ZN_MLo1Y.js +0 -2225
  27. package/exports/browser/connection-monitor-Cf0vNDCA.js +0 -453
  28. package/exports/browser/connection-monitor-pdopeM1I.js +0 -453
  29. package/exports/browser/hkdf-B9AXp_7K.js +0 -222
  30. package/exports/browser/index-Bxr5Iztg-Bdpw_E83.js +0 -40
  31. package/exports/browser/index-Bxr5Iztg-CxXVYm3t.js +0 -40
  32. package/exports/browser/index-CPQ5yvZ2.js +0 -4995
  33. package/exports/browser/index-uFaocBqT.js +0 -4995
  34. package/exports/browser/messages-DH0tgNM9-BRp0gcJh.js +0 -208
  35. package/exports/browser/messages-DH0tgNM9-DkNnpePH.js +0 -208
  36. package/exports/browser/node-browser-1VSuCeew.js +0 -17880
  37. package/exports/browser/node-browser-wDmRaOEo.js +0 -17880
  38. package/exports/browser/sha2-Dkoic3vb.js +0 -602
  39. package/exports/browser/weierstrass-HGdA_prK.js +0 -2156
@@ -1,453 +0,0 @@
1
- import { F as FormatInterface, o as proto$2, q as proto$3, i as index, f as index$1, r as proto$4 } from './browser-crypto-CTP3Yk4M.js';
2
-
3
- class ValidatorMessage extends FormatInterface {
4
- get messageName() {
5
- return "ValidatorMessage";
6
- }
7
- constructor(buffer) {
8
- if (buffer instanceof ValidatorMessage)
9
- return buffer;
10
- const name = "validator-message";
11
- super(buffer, proto$2, { name });
12
- }
13
- }
14
-
15
- class BlockMessage extends FormatInterface {
16
- get messageName() {
17
- return "BlockMessage";
18
- }
19
- constructor(buffer) {
20
- if (buffer instanceof BlockMessage)
21
- return buffer;
22
- const name = "block-message";
23
- super(buffer, proto$3, { name });
24
- }
25
- encode(decoded) {
26
- decoded = decoded || this.decoded;
27
- const validators = [];
28
- for (const validator of decoded.validators) {
29
- if (validator instanceof ValidatorMessage)
30
- validators.push(validator.encode());
31
- else
32
- validators.push(new ValidatorMessage(validator).encode());
33
- }
34
- return super.encode({
35
- ...decoded,
36
- validators: index(validators)
37
- });
38
- }
39
- decode(encoded) {
40
- encoded = encoded || this.encoded;
41
- super.decode(encoded);
42
- this.decoded.validators = index$1(this.decoded.validators).map((validator) => new ValidatorMessage(validator).decoded);
43
- return this.decoded;
44
- }
45
- }
46
-
47
- var proto$1 = {
48
- up: Number(),
49
- down: Number()
50
- };
51
-
52
- class BWMessage extends FormatInterface {
53
- get messageName() {
54
- return "BWMessage";
55
- }
56
- constructor(buffer) {
57
- if (buffer instanceof BWMessage)
58
- return buffer;
59
- const name = "bw-message";
60
- super(buffer, proto$1, { name });
61
- }
62
- }
63
-
64
- class LastBlockMessage extends FormatInterface {
65
- get messageName() {
66
- return "LastBlockMessage";
67
- }
68
- constructor(buffer) {
69
- if (buffer instanceof LastBlockMessage)
70
- return buffer;
71
- const name = "last-block-message";
72
- super(buffer, proto$4, { name });
73
- }
74
- }
75
-
76
- var proto = {
77
- lastblock: Object(),
78
- values: Object()
79
- };
80
-
81
- class StateMessage extends FormatInterface {
82
- get messageName() {
83
- return "StateMessage";
84
- }
85
- constructor(buffer) {
86
- if (buffer instanceof StateMessage)
87
- return buffer;
88
- const name = "state-message";
89
- super(buffer, proto, { name });
90
- }
91
- }
92
-
93
- var networks = {
94
- leofcoin: {
95
- mainnet: {
96
- // ports don't really matter since it is favorable to have it begind a ngninx proxy but if we change something to the proto it's easier maybe?
97
- port: 44444,
98
- // todo a versionhash would be nice to have as a double check?
99
- versionHash: "0",
100
- // a short description identifying the version
101
- description: "Main net current version",
102
- stars: ["wss://star.leofcoin.org"]
103
- // todo webrtc and bittorent stars
104
- },
105
- peach: {
106
- port: 44444,
107
- description: "Main testnet: latest step before merging into main",
108
- versionHash: "1",
109
- stars: ["wss://star.leofcoin.org"]
110
- // todo webrtc and bittorent stars
111
- }
112
- }
113
- };
114
-
115
- var networks$1 = /*#__PURE__*/Object.freeze({
116
- __proto__: null,
117
- default: networks
118
- });
119
-
120
- const PROTOCOL_VERSION = "0.3.0";
121
- const REACHED_ONE_ZERO_ZERO = false;
122
- const DEFAULT_NODE_OPTIONS = {
123
- autoStart: false,
124
- network: "leofcoin:peach",
125
- networkVersion: "peach",
126
- version: PROTOCOL_VERSION,
127
- stars: networks.leofcoin.peach.stars
128
- };
129
-
130
- const INITIAL_RECONNECT_DELAY = 5e3;
131
- const MAX_RECONNECT_DELAY = 3e4;
132
- const isSendablePeer = (peer) => {
133
- if (!peer || typeof peer !== "object") return false;
134
- const candidate = peer;
135
- if (typeof candidate.send !== "function") return false;
136
- if (candidate.connected === true) return true;
137
- return typeof candidate.once === "function" && typeof candidate.removeListener === "function";
138
- };
139
- const guardPeerMessages = (peernet) => {
140
- const sendMessage = peernet.sendMessage.bind(peernet);
141
- peernet.sendMessage = (peer, ...args) => {
142
- if (isSendablePeer(peer)) return sendMessage(peer, ...args);
143
- for (const [peerId, connection] of Object.entries(peernet.connections || {})) {
144
- if (connection === peer) delete peernet.connections[peerId];
145
- }
146
- return Promise.resolve(void 0);
147
- };
148
- };
149
- class ConnectionMonitor {
150
- #isMonitoring = false;
151
- #checkInterval = null;
152
- #reconnectDelay = INITIAL_RECONNECT_DELAY;
153
- #reconnectTimer = null;
154
- #healthCheckInterval = 6e4;
155
- #version;
156
- #lastHealthCheckAt = 0;
157
- #reconnecting = false;
158
- // event handlers to remove later
159
- #onOnline = null;
160
- #onVisibilityChange = null;
161
- #onSigcont = null;
162
- #onPeerConnected = null;
163
- get isMonitoring() {
164
- return this.#isMonitoring;
165
- }
166
- get connectedPeers() {
167
- return Object.values(globalThis.peernet?.connections || {}).filter((peer) => peer.connected);
168
- }
169
- get compatiblePeers() {
170
- return this.connectedPeers.filter((peer) => {
171
- if (!peer.version || !this.#version) return false;
172
- const [peerMajor, peerMinor] = peer.version.split(".");
173
- const [localMajor, localMinor] = this.#version.split(".");
174
- return peerMajor === localMajor && peerMinor === localMinor;
175
- });
176
- }
177
- get disconnectedPeers() {
178
- return Object.values(globalThis.peernet?.connections || {}).filter((peer) => !peer.connected);
179
- }
180
- #pruneInvalidConnections() {
181
- const connections = globalThis.peernet?.connections;
182
- if (!connections) return;
183
- for (const [peerId, peer] of Object.entries(connections)) {
184
- if (!isSendablePeer(peer)) {
185
- delete connections[peerId];
186
- console.warn(`Removed invalid peer connection: ${peerId}`);
187
- }
188
- }
189
- }
190
- start(version) {
191
- this.#version = version;
192
- console.log(`\u{1F517} Connection Monitor initialized for version: ${this.#version}`);
193
- if (this.#isMonitoring) return;
194
- this.#isMonitoring = true;
195
- console.log("\u{1F504} Starting connection monitor...");
196
- if (typeof window !== "undefined" && typeof document !== "undefined") {
197
- this.#onOnline = () => {
198
- console.log("\u{1F310} Network online \u2014 attempting restore");
199
- void this.#restoreNetwork();
200
- };
201
- window.addEventListener("online", this.#onOnline);
202
- this.#onVisibilityChange = () => {
203
- if (document.visibilityState === "visible") {
204
- console.log("\u{1F4A1} Visibility regained");
205
- if (this.connectedPeers.length === 0) {
206
- console.log("\u{1F4A1} Visibility regained \u2014 attempting restore");
207
- void this.#restoreNetwork();
208
- }
209
- }
210
- };
211
- document.addEventListener("visibilitychange", this.#onVisibilityChange);
212
- }
213
- if (typeof process !== "undefined" && typeof process.on === "function") {
214
- this.#onSigcont = () => {
215
- console.log("\u{1F514} Process resumed (SIGCONT) \u2014 attempting restore");
216
- void this.#restoreNetwork();
217
- };
218
- try {
219
- process.on("SIGCONT", this.#onSigcont);
220
- } catch (e) {
221
- }
222
- }
223
- this.#lastHealthCheckAt = Date.now();
224
- this.#checkInterval = setInterval(() => {
225
- this.#healthCheck();
226
- }, this.#healthCheckInterval);
227
- this.#onPeerConnected = () => {
228
- if (this.#reconnectTimer) {
229
- clearTimeout(this.#reconnectTimer);
230
- this.#reconnectTimer = null;
231
- }
232
- this.#reconnecting = false;
233
- this.#reconnectDelay = INITIAL_RECONNECT_DELAY;
234
- };
235
- globalThis.pubsub?.subscribe("peer:connected", this.#onPeerConnected);
236
- }
237
- stop() {
238
- if (!this.#isMonitoring) return;
239
- this.#isMonitoring = false;
240
- if (this.#checkInterval) {
241
- clearInterval(this.#checkInterval);
242
- this.#checkInterval = null;
243
- }
244
- if (typeof window !== "undefined") {
245
- if (this.#onOnline) {
246
- window.removeEventListener("online", this.#onOnline);
247
- this.#onOnline = null;
248
- }
249
- if (this.#onVisibilityChange) {
250
- document.removeEventListener("visibilitychange", this.#onVisibilityChange);
251
- this.#onVisibilityChange = null;
252
- }
253
- }
254
- if (typeof process !== "undefined" && typeof process.removeListener === "function" && this.#onSigcont) {
255
- try {
256
- process.removeListener("SIGCONT", this.#onSigcont);
257
- } catch (e) {
258
- }
259
- this.#onSigcont = null;
260
- }
261
- if (this.#onPeerConnected) {
262
- globalThis.pubsub?.unsubscribe("peer:connected", this.#onPeerConnected);
263
- this.#onPeerConnected = null;
264
- }
265
- if (this.#reconnectTimer) {
266
- clearTimeout(this.#reconnectTimer);
267
- this.#reconnectTimer = null;
268
- }
269
- console.log("\u23F9\uFE0F Connection monitor stopped");
270
- }
271
- async #healthCheck() {
272
- this.#pruneInvalidConnections();
273
- const now = Date.now();
274
- const expectedNext = this.#lastHealthCheckAt + this.#healthCheckInterval;
275
- const drift = now - expectedNext;
276
- this.#lastHealthCheckAt = now;
277
- if (drift > 5e3) {
278
- console.log(`\u23F0 Detected timer drift of ${drift}ms (likely system sleep) \u2014 attempting restore`);
279
- void this.#restoreNetwork();
280
- }
281
- const connectedPeers = this.connectedPeers;
282
- const compatiblePeers = this.compatiblePeers;
283
- const disconnectedPeers = this.disconnectedPeers;
284
- console.log(
285
- `\u{1F50D} Health check: ${connectedPeers.length} connected, ${compatiblePeers.length} compatible, ${disconnectedPeers.length} negotiating`
286
- );
287
- if (connectedPeers.length === 0 && disconnectedPeers.length === 0 && !this.#reconnectTimer) {
288
- console.warn("\u26A0\uFE0F No peer connections detected \u2014 attempting reconnection");
289
- await this.#attemptReconnection();
290
- } else if (compatiblePeers.length === 0 && connectedPeers.length > 0 && !this.#reconnectTimer) {
291
- console.warn("\u26A0\uFE0F No compatible peers found \u2014 attempting reconnection");
292
- await this.#attemptReconnection();
293
- }
294
- globalThis.pubsub?.publish("connection-status", {
295
- connected: connectedPeers.length,
296
- compatible: compatiblePeers.length,
297
- healthy: compatiblePeers.length > 0
298
- });
299
- }
300
- // lightweight TCP probe to detect internet connectivity in Node.js
301
- async #isOnLine(timeout = 1500) {
302
- if (navigator?.onLine !== void 0) {
303
- return navigator.onLine;
304
- }
305
- return new Promise(async (resolve) => {
306
- try {
307
- const net = await import('net');
308
- const socket = new net.Socket();
309
- let finished = false;
310
- const finish = (val) => {
311
- if (finished) return;
312
- finished = true;
313
- try {
314
- socket.destroy();
315
- } catch (e) {
316
- }
317
- resolve(val);
318
- };
319
- socket.setTimeout(timeout);
320
- socket.once("connect", () => finish(true));
321
- socket.once("error", () => finish(false));
322
- socket.once("timeout", () => finish(false));
323
- socket.connect(53, "1.1.1.1");
324
- } catch (e) {
325
- resolve(false);
326
- }
327
- });
328
- }
329
- // Called on visibility/online/resume events
330
- async #restoreNetwork() {
331
- if (this.#reconnecting) {
332
- console.log("\u{1F501} Reconnection already in progress, skipping");
333
- return;
334
- }
335
- this.#reconnecting = true;
336
- if (this.connectedPeers.length > 0) {
337
- console.log("\u2705 Already connected to peers, skipping restoration");
338
- this.#reconnecting = false;
339
- return;
340
- }
341
- console.log("\u{1F501} Restoring network");
342
- try {
343
- const online = await this.#isOnLine(1500);
344
- if (!online) {
345
- console.warn("\u26A0\uFE0F No internet detected, skipping restore");
346
- this.#reconnecting = false;
347
- return;
348
- }
349
- } catch (e) {
350
- console.warn("\u26A0\uFE0F Online probe failed, proceeding with restore", e?.message || e);
351
- }
352
- try {
353
- console.log("\u{1F504} Attempting network restoration...");
354
- if (globalThis.peernet?.client?.reinit) {
355
- console.log(" \u2192 Trying client.reinit()");
356
- try {
357
- await globalThis.peernet.client.reinit();
358
- console.log(" \u2705 client.reinit() succeeded");
359
- } catch (e) {
360
- console.warn(" \u26A0\uFE0F client.reinit() failed:", e?.message || e);
361
- }
362
- }
363
- if (globalThis.peernet?.start) {
364
- console.log(" \u2192 Trying peernet.start()");
365
- try {
366
- await globalThis.peernet.start();
367
- console.log(" \u2705 peernet.start() succeeded");
368
- } catch (e) {
369
- console.warn(" \u26A0\uFE0F peernet.start() failed:", e?.message || e);
370
- }
371
- }
372
- try {
373
- const networkName = globalThis.peernet?.network;
374
- if (networkName && typeof networkName === "string") {
375
- const { default: networks } = await Promise.resolve().then(function () { return networks$1; });
376
- const [mainKey, subKey] = networkName.split(":");
377
- const networkConfig = networks?.[mainKey]?.[subKey];
378
- if (networkConfig?.stars && Array.isArray(networkConfig.stars)) {
379
- console.log(" \u2192 Attempting to dial star servers:", networkConfig.stars.join(", "));
380
- for (const star of networkConfig.stars) {
381
- try {
382
- if (globalThis.peernet?.client && "dial" in globalThis.peernet.client) {
383
- await globalThis.peernet.client.dial(star);
384
- console.log(` \u2705 Connected to star server: ${star}`);
385
- }
386
- } catch (e) {
387
- console.warn(` \u26A0\uFE0F Failed to dial ${star}:`, e?.message || e);
388
- }
389
- }
390
- }
391
- }
392
- } catch (e) {
393
- console.warn(" \u26A0\uFE0F Could not load or dial star servers:", e?.message || e);
394
- }
395
- await new Promise((resolve) => setTimeout(resolve, 2e3));
396
- this.#pruneInvalidConnections();
397
- const connectedAfter = this.connectedPeers.length;
398
- console.log(`\u{1F504} Restoration complete. Connected peers: ${connectedAfter}`);
399
- } catch (error) {
400
- console.error("\u274C Network restoration failed:", error?.message || error);
401
- } finally {
402
- this.#reconnecting = false;
403
- }
404
- }
405
- async waitForPeers(timeoutMs = 3e4) {
406
- return new Promise((resolve) => {
407
- const startTime = Date.now();
408
- const checkPeers = () => {
409
- if (this.compatiblePeers.length > 0) {
410
- resolve(true);
411
- return;
412
- }
413
- if (Date.now() - startTime >= timeoutMs) {
414
- resolve(false);
415
- return;
416
- }
417
- setTimeout(checkPeers, 1e3);
418
- };
419
- checkPeers();
420
- });
421
- }
422
- async #attemptReconnection() {
423
- try {
424
- await this.#restoreNetwork();
425
- const hasConnections = this.connectedPeers.length > 0 || this.disconnectedPeers.length > 0;
426
- if (hasConnections) {
427
- console.log("\u2705 Reconnection successful, resetting backoff delay");
428
- this.#reconnectDelay = INITIAL_RECONNECT_DELAY;
429
- } else {
430
- console.warn("\u26A0\uFE0F Reconnection attempt completed but no peers connected");
431
- this.#scheduleReconnect();
432
- }
433
- } catch (error) {
434
- console.error("\u274C Reconnection failed:", error?.message || error);
435
- this.#scheduleReconnect();
436
- }
437
- }
438
- #scheduleReconnect() {
439
- if (!this.#isMonitoring || this.#reconnectTimer) return;
440
- if (this.#reconnectDelay >= MAX_RECONNECT_DELAY) {
441
- console.warn("\u26A0\uFE0F No peers available; automatic retries paused until the next health check or network event");
442
- return;
443
- }
444
- this.#reconnectDelay = Math.min(this.#reconnectDelay * 1.5, MAX_RECONNECT_DELAY);
445
- console.warn(`\u26A0\uFE0F Increasing reconnection delay to ${this.#reconnectDelay} ms`);
446
- this.#reconnectTimer = setTimeout(() => {
447
- this.#reconnectTimer = null;
448
- void this.#attemptReconnection();
449
- }, this.#reconnectDelay);
450
- }
451
- }
452
-
453
- export { BlockMessage as B, ConnectionMonitor as C, DEFAULT_NODE_OPTIONS as D, LastBlockMessage as L, PROTOCOL_VERSION as P, REACHED_ONE_ZERO_ZERO as R, StateMessage as S, ValidatorMessage as V, BWMessage as a, guardPeerMessages as g };
@@ -1,222 +0,0 @@
1
- import { a as ahash, b as abytes, c as clean, d as aexists, e as aoutput, f as anumber } from './sha2-Dkoic3vb.js';
2
-
3
- /**
4
- * HMAC: RFC2104 message authentication code.
5
- * @module
6
- */
7
- /**
8
- * Internal class for HMAC.
9
- * Accepts any byte key, although RFC 2104 §3 recommends keys at least
10
- * `HashLen` bytes long.
11
- */
12
- class _HMAC {
13
- oHash;
14
- iHash;
15
- blockLen;
16
- outputLen;
17
- canXOF = false;
18
- finished = false;
19
- destroyed = false;
20
- constructor(hash, key) {
21
- ahash(hash);
22
- abytes(key, undefined, 'key');
23
- this.iHash = hash.create();
24
- if (typeof this.iHash.update !== 'function')
25
- throw new Error('expected Hash instance');
26
- this.blockLen = this.iHash.blockLen;
27
- this.outputLen = this.iHash.outputLen;
28
- const blockLen = this.blockLen;
29
- const pad = new Uint8Array(blockLen);
30
- // blockLen can be bigger than outputLen
31
- pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
32
- for (let i = 0; i < pad.length; i++)
33
- pad[i] ^= 0x36;
34
- this.iHash.update(pad);
35
- // By doing update (processing of the first block) of the outer hash here,
36
- // we can re-use it between multiple calls via clone.
37
- this.oHash = hash.create();
38
- // Undo internal XOR && apply outer XOR
39
- for (let i = 0; i < pad.length; i++)
40
- pad[i] ^= 0x36 ^ 0x5c;
41
- this.oHash.update(pad);
42
- clean(pad);
43
- }
44
- update(buf) {
45
- aexists(this);
46
- this.iHash.update(buf);
47
- return this;
48
- }
49
- digestInto(out) {
50
- aexists(this);
51
- aoutput(out, this);
52
- this.finished = true;
53
- const buf = out.subarray(0, this.outputLen);
54
- // Reuse the first outputLen bytes for the inner digest; the outer hash consumes them before
55
- // overwriting that same prefix with the final tag, leaving any oversized tail untouched.
56
- this.iHash.digestInto(buf);
57
- this.oHash.update(buf);
58
- this.oHash.digestInto(buf);
59
- this.destroy();
60
- }
61
- digest() {
62
- const out = new Uint8Array(this.oHash.outputLen);
63
- this.digestInto(out);
64
- return out;
65
- }
66
- _cloneInto(to) {
67
- // Create new instance without calling constructor since the key
68
- // is already in state and we don't know it.
69
- to ||= Object.create(Object.getPrototypeOf(this), {});
70
- const { oHash, iHash, finished, destroyed, blockLen, outputLen, canXOF } = this;
71
- to = to;
72
- to.finished = finished;
73
- to.destroyed = destroyed;
74
- to.blockLen = blockLen;
75
- to.outputLen = outputLen;
76
- to.canXOF = canXOF;
77
- to.oHash = oHash._cloneInto(to.oHash);
78
- to.iHash = iHash._cloneInto(to.iHash);
79
- return to;
80
- }
81
- clone() {
82
- return this._cloneInto();
83
- }
84
- destroy() {
85
- this.destroyed = true;
86
- this.oHash.destroy();
87
- this.iHash.destroy();
88
- }
89
- }
90
- const hmac = /* @__PURE__ */ (() => {
91
- const hmac_ = ((hash, key, message) => new _HMAC(hash, key).update(message).digest());
92
- hmac_.create = (hash, key) => new _HMAC(hash, key);
93
- return hmac_;
94
- })();
95
-
96
- /**
97
- * HKDF (RFC 5869): extract + expand in one step.
98
- * See {@link https://soatok.blog/2021/11/17/understanding-hkdf/}.
99
- * @module
100
- */
101
- // Shared mutable scratch byte for the RFC 5869 block counter `N`.
102
- // Safe to reuse because `expand()` is synchronous and resets it with `clean(...)` before returning.
103
- const HKDF_COUNTER = /* @__PURE__ */ Uint8Array.of(0);
104
- // Shared RFC 5869 empty string for both `info === undefined` and the first-block `T(0)` input.
105
- const EMPTY_BUFFER = /* @__PURE__ */ Uint8Array.of();
106
- /**
107
- * HKDF-expand from the spec. The most important part. `HKDF-Expand(PRK, info, L) -> OKM`
108
- * @param hash - hash function that would be used (e.g. sha256)
109
- * @param prk - a pseudorandom key of at least HashLen octets
110
- * (usually, the output from the extract step)
111
- * @param info - optional context and application specific information (can be a zero-length string)
112
- * @param length - length of output keying material in bytes.
113
- * RFC 5869 §2.3 allows `0..255*HashLen`, so `0` returns an empty OKM.
114
- * @param _recycled - Internal destroyed extract hashes owned by the combined `hkdf()` call.
115
- * @returns Output keying material with the requested length.
116
- * @throws If the requested output length exceeds the HKDF limit
117
- * for the selected hash. {@link Error}
118
- * @example
119
- * Run the HKDF expand step.
120
- * ```ts
121
- * import { expand } from '@noble/hashes/hkdf.js';
122
- * import { sha256 } from '@noble/hashes/sha2.js';
123
- * expand(sha256, new Uint8Array(32), new Uint8Array([1, 2, 3]), 16);
124
- * ```
125
- */
126
- function expand(hash, prk, info, length = 32, _recycled) {
127
- ahash(hash);
128
- anumber(length, 'length');
129
- abytes(prk, undefined, 'prk');
130
- const olen = hash.outputLen;
131
- // RFC 5869 §2.3: PRK is "a pseudorandom key of at least HashLen octets".
132
- if (prk.length < olen)
133
- throw new Error('"prk" must be at least HashLen octets');
134
- // RFC 5869 §2.3 only bounds `L` by `<= 255*HashLen`; `L=0` is valid and yields empty OKM.
135
- if (length > 255 * olen)
136
- throw new Error('Length must be <= 255*HashLen');
137
- const blocks = Math.ceil(length / olen);
138
- if (info === undefined)
139
- info = EMPTY_BUFFER;
140
- else
141
- abytes(info, undefined, 'info');
142
- if (!blocks) {
143
- if (_recycled)
144
- clean(prk); // Full hkdf() owns this intermediate PRK.
145
- return new Uint8Array();
146
- }
147
- // first L(ength) octets of T
148
- // The private PRK can become both T and a one-block result after HMAC consumes the key.
149
- const okm = _recycled && blocks === 1 ? prk : new Uint8Array(blocks * olen);
150
- const { iHash, oHash } = hmac.create(hash, prk);
151
- // Driving them directly also skips `_HMAC.digestInto`'s per-digest destroy.
152
- const T = _recycled ? prk : new Uint8Array(olen);
153
- // Full hkdf() donates one destroyed extract hash; standalone creates one alternating worker.
154
- const worker = blocks > 1 ? _recycled?.iHash || hash.create() : undefined;
155
- for (let counter = 0; counter < blocks - 1; counter++) {
156
- HKDF_COUNTER[0] = counter + 1;
157
- const iWork = iHash._cloneInto(worker);
158
- // T(0) = empty string (zero length)
159
- // T(N) = HMAC-Hash(PRK, T(N-1) | info | N)
160
- if (counter)
161
- iWork.update(T);
162
- iWork.update(info).update(HKDF_COUNTER).digestInto(T);
163
- oHash._cloneInto(worker).update(T).digestInto(T);
164
- okm.set(T, olen * counter);
165
- }
166
- // Midstates are key-equivalent: they allow computing HMAC(prk, ...) for any message.
167
- HKDF_COUNTER[0] = blocks; // Final block consumes them; retain worker for cleanup.
168
- if (blocks > 1)
169
- iHash.update(T);
170
- iHash.update(info).update(HKDF_COUNTER).digestInto(T);
171
- oHash.update(T).digestInto(T);
172
- okm.set(T, olen * (blocks - 1));
173
- iHash.destroy(); // Raw digests may leave key-derived base/worker state; wipe all explicitly.
174
- oHash.destroy();
175
- worker?.destroy();
176
- if (T !== okm)
177
- clean(T); // Wipe private T/PRK; standalone preserves caller-owned PRK.
178
- clean(HKDF_COUNTER);
179
- // Exact fit: return without the extra copy.
180
- if (length === okm.length)
181
- return okm;
182
- // Copy the requested prefix, then wipe the full buffer: its tail holds
183
- // up to HashLen-1 bytes of derived key material past `length`.
184
- const res = okm.slice(0, length);
185
- clean(okm);
186
- return res;
187
- }
188
- /**
189
- * HKDF (RFC 5869): derive keys from an initial input.
190
- * Combines hkdf_extract + hkdf_expand in one step
191
- * @param hash - hash function that would be used (e.g. sha256)
192
- * @param ikm - input keying material, the initial key
193
- * @param salt - optional salt value (a non-secret random value)
194
- * @param info - optional context and application specific information bytes
195
- * @param length - length of output keying material in bytes.
196
- * RFC 5869 §2.3 allows `0..255*HashLen`, so `0` returns an empty OKM.
197
- * @returns Output keying material derived from the input key.
198
- * @throws If the requested output length exceeds the HKDF limit
199
- * for the selected hash. {@link Error}
200
- * @example
201
- * HKDF (RFC 5869): derive keys from an initial input.
202
- * ```ts
203
- * import { hkdf } from '@noble/hashes/hkdf.js';
204
- * import { sha256 } from '@noble/hashes/sha2.js';
205
- * import { randomBytes, utf8ToBytes } from '@noble/hashes/utils.js';
206
- * const inputKey = randomBytes(32);
207
- * const salt = randomBytes(32);
208
- * const info = utf8ToBytes('application-key');
209
- * const okm = hkdf(sha256, inputKey, salt, info, 32);
210
- * ```
211
- */
212
- const hkdf = (hash, ikm, salt, info, length) => {
213
- ahash(hash);
214
- if (salt === undefined)
215
- salt = new Uint8Array(hash.outputLen);
216
- const HMAC = hmac.create(hash, salt).update(ikm);
217
- // The intermediate PRK is secret key material; wipe it instead of
218
- // leaving it for GC.
219
- return expand(hash, HMAC.digest(), info, length, HMAC); // expand() owns and consumes it.
220
- };
221
-
222
- export { hkdf as h };