@optimystic/quereus-plugin-crypto 0.13.4 → 0.14.1

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/dist/index.js CHANGED
@@ -1,11 +1,17 @@
1
1
  import { sha512, sha256 } from '@noble/hashes/sha2.js';
2
2
  import { blake3 } from '@noble/hashes/blake3.js';
3
- import { randomBytes as randomBytes$1, concatBytes, utf8ToBytes } from '@noble/hashes/utils.js';
3
+ import { concatBytes, randomBytes as randomBytes$1, utf8ToBytes } from '@noble/hashes/utils.js';
4
4
  import { secp256k1 } from '@noble/curves/secp256k1.js';
5
5
  import { p256 } from '@noble/curves/nist.js';
6
6
  import { ed25519 } from '@noble/curves/ed25519.js';
7
- import { hexToBytes, bytesToHex } from '@noble/curves/utils.js';
8
- import { fromString, toString } from 'uint8arrays';
7
+ import { bytesToHex, hexToBytes } from '@noble/curves/utils.js';
8
+ import { toString, fromString } from 'uint8arrays';
9
+ import { CID } from 'multiformats/cid';
10
+ import * as Digest from 'multiformats/hashes/digest';
11
+ import { base32 } from 'multiformats/bases/base32';
12
+ import { base58btc } from 'multiformats/bases/base58';
13
+ import { base64url } from 'multiformats/bases/base64';
14
+ import { base16 } from 'multiformats/bases/base16';
9
15
 
10
16
  // src/crypto.ts
11
17
  function toBytes(input, encoding = "base64url") {
@@ -47,29 +53,136 @@ function fromBytes(bytes, encoding = "base64url") {
47
53
  return toString(bytes, "base64url");
48
54
  }
49
55
  }
50
- function digest(data, algorithm = "sha256", inputEncoding = "base64url", outputEncoding = "base64url") {
51
- const bytes = toBytes(data, inputEncoding);
52
- let hashBytes;
53
- switch (algorithm) {
54
- case "sha256":
55
- hashBytes = sha256(bytes);
56
- break;
57
- case "sha512":
58
- hashBytes = sha512(bytes);
59
- break;
60
- case "blake3":
61
- hashBytes = blake3(bytes);
62
- break;
56
+ var HASHERS = {
57
+ sha256,
58
+ sha512,
59
+ blake3
60
+ };
61
+ var OUTPUT_ENCODERS = {
62
+ base64url: (bytes) => toString(bytes, "base64url"),
63
+ base64: (bytes) => toString(bytes, "base64"),
64
+ hex: (bytes) => bytesToHex(bytes),
65
+ bytes: (bytes) => bytes
66
+ };
67
+ function resolveHasher(algorithm) {
68
+ const hasher = HASHERS[algorithm];
69
+ if (!hasher) {
70
+ throw new Error(`Unsupported hash algorithm: ${algorithm}`);
71
+ }
72
+ return hasher;
73
+ }
74
+ function resolveOutputEncoder(encoding) {
75
+ const encoder = OUTPUT_ENCODERS[encoding];
76
+ if (!encoder) {
77
+ throw new Error(`Unsupported output encoding: ${encoding}`);
78
+ }
79
+ return encoder;
80
+ }
81
+ var DIGEST_FORMAT_V1 = 1;
82
+ var TAG_NULL = 0;
83
+ var TAG_INT = 1;
84
+ var TAG_REAL = 2;
85
+ var TAG_TEXT = 3;
86
+ var TAG_BOOL = 4;
87
+ var TAG_BLOB = 5;
88
+ var TAG_JSON = 6;
89
+ function writeVarint(out, value) {
90
+ if (!Number.isInteger(value) || value < 0) {
91
+ throw new Error(`varint expects a non-negative integer, got ${value}`);
92
+ }
93
+ let v = value;
94
+ while (v >= 128) {
95
+ out.push(v & 127 | 128);
96
+ v = Math.floor(v / 128);
97
+ }
98
+ out.push(v);
99
+ }
100
+ function framed(tag, payload) {
101
+ const header = [tag];
102
+ writeVarint(header, payload.length);
103
+ return concatBytes(Uint8Array.from(header), payload);
104
+ }
105
+ function canonicalJson(value) {
106
+ if (value === null) return "null";
107
+ const t = typeof value;
108
+ if (t === "string") return JSON.stringify(value);
109
+ if (t === "boolean") return value ? "true" : "false";
110
+ if (t === "number") {
111
+ if (!Number.isFinite(value)) {
112
+ throw new Error("digest: cannot encode a non-finite number inside a JSON field");
113
+ }
114
+ return JSON.stringify(value);
115
+ }
116
+ if (t === "bigint") {
117
+ throw new Error("digest: bigint is not representable inside a JSON field");
118
+ }
119
+ if (Array.isArray(value)) {
120
+ return `[${value.map((el) => {
121
+ if (el === void 0) {
122
+ throw new Error("digest: undefined / sparse element inside a JSON field");
123
+ }
124
+ return canonicalJson(el);
125
+ }).join(",")}]`;
126
+ }
127
+ if (t === "object") {
128
+ const proto = Object.getPrototypeOf(value);
129
+ if (proto !== Object.prototype && proto !== null) {
130
+ throw new Error("digest: only plain objects are allowed inside a JSON field");
131
+ }
132
+ const obj = value;
133
+ const keys = Object.keys(obj).sort();
134
+ return `{${keys.map((k) => {
135
+ if (obj[k] === void 0) {
136
+ throw new Error(`digest: undefined value for JSON key '${k}'`);
137
+ }
138
+ return `${JSON.stringify(k)}:${canonicalJson(obj[k])}`;
139
+ }).join(",")}}`;
140
+ }
141
+ throw new Error(`digest: unsupported value of type '${t}' inside a JSON field`);
142
+ }
143
+ function encodeField(field) {
144
+ if (field === null || field === void 0) {
145
+ return Uint8Array.of(TAG_NULL);
146
+ }
147
+ switch (typeof field) {
148
+ case "boolean":
149
+ return Uint8Array.of(TAG_BOOL, field ? 1 : 0);
150
+ case "bigint":
151
+ return framed(TAG_INT, utf8ToBytes(field.toString()));
152
+ case "number":
153
+ if (!Number.isFinite(field)) {
154
+ throw new Error("digest: cannot encode a non-finite number");
155
+ }
156
+ return Number.isInteger(field) ? framed(TAG_INT, utf8ToBytes(BigInt(field).toString())) : framed(TAG_REAL, utf8ToBytes(field.toString()));
157
+ case "string":
158
+ return framed(TAG_TEXT, utf8ToBytes(field));
159
+ case "object":
160
+ if (field instanceof Uint8Array) {
161
+ return framed(TAG_BLOB, field);
162
+ }
163
+ return framed(TAG_JSON, utf8ToBytes(canonicalJson(field)));
63
164
  default:
64
- throw new Error(`Unsupported hash algorithm: ${algorithm}`);
165
+ throw new Error(`digest: unsupported field type '${typeof field}'`);
166
+ }
167
+ }
168
+ function encodeFields(fields) {
169
+ const chunks = [Uint8Array.of(DIGEST_FORMAT_V1)];
170
+ for (const field of fields) {
171
+ chunks.push(encodeField(field));
65
172
  }
66
- return fromBytes(hashBytes, outputEncoding);
173
+ return concatBytes(...chunks);
174
+ }
175
+ function digestFields(fields, hasher, encode) {
176
+ return encode(hasher(encodeFields(fields)));
177
+ }
178
+ function digest(fields, algorithm = "sha256", encoding = "base64url") {
179
+ return digestFields(fields, resolveHasher(algorithm), resolveOutputEncoder(encoding));
67
180
  }
68
181
  function hashMod(data, bits, algorithm = "sha256", inputEncoding = "base64url") {
69
182
  if (bits <= 0 || bits > 53) {
70
183
  throw new Error("Bits must be between 1 and 53 (JavaScript safe integer limit)");
71
184
  }
72
- const hashBytes = toBytes(digest(data, algorithm, inputEncoding, "base64url"), "base64url");
185
+ const hashBytes = resolveHasher(algorithm)(toBytes(data, inputEncoding));
73
186
  const view = new DataView(hashBytes.buffer, hashBytes.byteOffset, Math.min(8, hashBytes.length));
74
187
  const fullHash = view.getBigUint64(0, false);
75
188
  const modulus = BigInt(2) ** BigInt(bits);
@@ -157,285 +270,167 @@ function getPublicKey(privateKey, curve = "secp256k1", keyEncoding = "base64url"
157
270
  }
158
271
  return fromBytes(pubBytes, outputEncoding);
159
272
  }
160
- function inputToBytes(input) {
161
- if (input === null || input === void 0) {
162
- return new Uint8Array(0);
163
- }
164
- if (typeof input === "string") {
165
- return utf8ToBytes(input);
166
- }
167
- if (input instanceof Uint8Array) {
168
- return input;
169
- }
170
- if (typeof input === "number") {
171
- const buffer = new ArrayBuffer(8);
172
- const view = new DataView(buffer);
173
- view.setFloat64(0, input, false);
174
- return new Uint8Array(buffer);
175
- }
176
- if (typeof input === "boolean") {
177
- return new Uint8Array([input ? 1 : 0]);
178
- }
179
- return utf8ToBytes(String(input));
180
- }
181
- function getHashFunction(algorithm) {
182
- switch (algorithm) {
183
- case "sha256":
184
- return sha256;
185
- case "sha512":
186
- return sha512;
187
- case "blake3":
188
- return blake3;
189
- default:
190
- throw new Error(`Unsupported hash algorithm: ${algorithm}`);
191
- }
192
- }
193
- function Digest(...args) {
194
- return DigestWithOptions({ algorithm: "sha256", output: "uint8array" }, ...args);
195
- }
196
- function DigestWithOptions(options, ...args) {
197
- const algorithm = options.algorithm || "sha256";
198
- const output = options.output || "uint8array";
199
- const byteArrays = args.map(inputToBytes);
200
- const combined = concatBytes(...byteArrays);
201
- const hashFunction = getHashFunction(algorithm);
202
- const hash = hashFunction(combined);
203
- if (output === "hex") {
204
- return Array.from(hash).map((b) => b.toString(16).padStart(2, "0")).join("");
205
- }
206
- return hash;
207
- }
208
- Digest.withOptions = (options) => {
209
- return (...args) => DigestWithOptions(options, ...args);
210
- };
211
- Digest.sha256 = (...args) => {
212
- return DigestWithOptions({ algorithm: "sha256" }, ...args);
213
- };
214
- Digest.sha512 = (...args) => {
215
- return DigestWithOptions({ algorithm: "sha512" }, ...args);
273
+ var MULTICODEC_CODES = {
274
+ "raw": 85,
275
+ "dag-cbor": 113
216
276
  };
217
- Digest.blake3 = (...args) => {
218
- return DigestWithOptions({ algorithm: "blake3" }, ...args);
277
+ var MULTIHASH_CODES = {
278
+ "sha2-256": 18,
279
+ "sha2-512": 19,
280
+ "blake3": 30
219
281
  };
220
- Digest.hex = (...args) => {
221
- return DigestWithOptions({ algorithm: "sha256", output: "hex" }, ...args);
282
+ var MULTIHASH_TO_ALGORITHM = {
283
+ "sha2-256": "sha256",
284
+ "sha2-512": "sha512",
285
+ "blake3": "blake3"
222
286
  };
223
- Digest.sha256Hex = (...args) => {
224
- return DigestWithOptions({ algorithm: "sha256", output: "hex" }, ...args);
287
+ var MULTIHASH_DIGEST_LENGTHS = {
288
+ "sha2-256": 32,
289
+ "sha2-512": 64,
290
+ "blake3": 32
225
291
  };
226
- Digest.sha512Hex = (...args) => {
227
- return DigestWithOptions({ algorithm: "sha512", output: "hex" }, ...args);
292
+ var MULTICODEC_NAMES = new Map(
293
+ Object.entries(MULTICODEC_CODES).map(([name, code]) => [code, name])
294
+ );
295
+ var MULTIHASH_NAMES = new Map(
296
+ Object.entries(MULTIHASH_CODES).map(([name, code]) => [code, name])
297
+ );
298
+ var MULTIBASE_ENCODERS = {
299
+ "base32": base32,
300
+ "base58btc": base58btc,
301
+ "base64url": base64url,
302
+ "base16": base16
228
303
  };
229
- Digest.blake3Hex = (...args) => {
230
- return DigestWithOptions({ algorithm: "blake3", output: "hex" }, ...args);
231
- };
232
- function normalizePrivateKey(privateKey) {
233
- if (privateKey instanceof Uint8Array) {
234
- return privateKey;
235
- }
236
- if (typeof privateKey === "string") {
237
- return hexToBytes(privateKey);
238
- }
239
- if (typeof privateKey === "bigint") {
240
- const hex = privateKey.toString(16).padStart(64, "0");
241
- return hexToBytes(hex);
304
+ var MULTIBASE_DECODER = base32.decoder.or(base58btc.decoder).or(base64url.decoder).or(base16.decoder);
305
+ function resolveCodecCode(codec) {
306
+ const code = MULTICODEC_CODES[codec];
307
+ if (code === void 0) {
308
+ throw new Error(`cid: unsupported multicodec '${codec}' (expected one of ${Object.keys(MULTICODEC_CODES).join(", ")})`);
242
309
  }
243
- throw new Error("Invalid private key format");
310
+ return code;
244
311
  }
245
- function normalizeDigest(digest2) {
246
- if (digest2 instanceof Uint8Array) {
247
- return digest2;
312
+ function resolveBaseEncoder(base) {
313
+ const encoder = MULTIBASE_ENCODERS[base];
314
+ if (!encoder) {
315
+ throw new Error(`cid: unsupported multibase '${base}' (expected one of ${Object.keys(MULTIBASE_ENCODERS).join(", ")})`);
248
316
  }
249
- if (typeof digest2 === "string") {
250
- return hexToBytes(digest2);
251
- }
252
- throw new Error("Invalid digest format");
317
+ return encoder;
253
318
  }
254
- function formatSignature(signature, format, curve) {
255
- switch (format) {
256
- case "uint8array":
257
- case "compact":
258
- return signature;
259
- case "hex":
260
- return bytesToHex(signature);
261
- case "der":
262
- if (curve === "ed25519") {
263
- throw new Error("DER format not supported for ed25519");
264
- }
265
- return signature;
266
- default:
267
- throw new Error(`Unsupported signature format: ${format}`);
268
- }
319
+ function cidV1(digest2, hash, codec = "raw", base = "base32") {
320
+ const hashCode = MULTIHASH_CODES[hash];
321
+ if (hashCode === void 0) {
322
+ throw new Error(`cid: unsupported multihash code '${hash}' (expected one of ${Object.keys(MULTIHASH_CODES).join(", ")})`);
323
+ }
324
+ const expectedLength = MULTIHASH_DIGEST_LENGTHS[hash];
325
+ if (digest2.length !== expectedLength) {
326
+ throw new Error(`cid: digest length ${digest2.length} does not match asserted hash '${hash}' (expected ${expectedLength} bytes)`);
327
+ }
328
+ const codecCode = resolveCodecCode(codec);
329
+ const encoder = resolveBaseEncoder(base);
330
+ const multihash = Digest.create(hashCode, digest2);
331
+ return CID.createV1(codecCode, multihash).toString(encoder);
269
332
  }
270
- function Sign(digest2, privateKey, options = {}) {
271
- const {
272
- curve = "secp256k1",
273
- format = "uint8array",
274
- extraEntropy = false,
275
- lowS = true
276
- } = options;
277
- const normalizedDigest = normalizeDigest(digest2);
278
- const normalizedPrivateKey = normalizePrivateKey(privateKey);
279
- let signature;
280
- switch (curve) {
281
- case "secp256k1": {
282
- const signOptions = { lowS };
283
- if (extraEntropy) {
284
- signOptions.extraEntropy = extraEntropy;
285
- }
286
- signature = secp256k1.sign(normalizedDigest, normalizedPrivateKey, signOptions);
287
- break;
288
- }
289
- case "p256": {
290
- const signOptions = { lowS };
291
- if (extraEntropy) {
292
- signOptions.extraEntropy = extraEntropy;
293
- }
294
- signature = p256.sign(normalizedDigest, normalizedPrivateKey, signOptions);
295
- break;
296
- }
297
- case "ed25519": {
298
- signature = ed25519.sign(normalizedDigest, normalizedPrivateKey);
299
- break;
300
- }
301
- default:
302
- throw new Error(`Unsupported curve: ${curve}`);
333
+ function cid(data, codec = "raw", hash = "sha2-256", base = "base32") {
334
+ const algorithm = MULTIHASH_TO_ALGORITHM[hash];
335
+ if (!algorithm) {
336
+ throw new Error(`cid: unsupported multihash code '${hash}' (expected one of ${Object.keys(MULTIHASH_CODES).join(", ")})`);
303
337
  }
304
- return formatSignature(signature, format, curve);
338
+ const digest2 = resolveHasher(algorithm)(data);
339
+ return cidV1(digest2, hash, codec, base);
305
340
  }
306
- Sign.secp256k1 = (digest2, privateKey, options = {}) => {
307
- return Sign(digest2, privateKey, { ...options, curve: "secp256k1" });
308
- };
309
- Sign.p256 = (digest2, privateKey, options = {}) => {
310
- return Sign(digest2, privateKey, { ...options, curve: "p256" });
311
- };
312
- Sign.ed25519 = (digest2, privateKey, options = {}) => {
313
- return Sign(digest2, privateKey, { ...options, curve: "ed25519" });
314
- };
315
- Sign.generatePrivateKey = (curve = "secp256k1") => {
316
- switch (curve) {
317
- case "secp256k1":
318
- return secp256k1.utils.randomSecretKey();
319
- case "p256":
320
- return p256.utils.randomSecretKey();
321
- case "ed25519":
322
- return ed25519.utils.randomSecretKey();
323
- default:
324
- throw new Error(`Unsupported curve: ${curve}`);
325
- }
326
- };
327
- Sign.getPublicKey = (privateKey, curve = "secp256k1") => {
328
- const normalizedPrivateKey = normalizePrivateKey(privateKey);
329
- switch (curve) {
330
- case "secp256k1":
331
- return secp256k1.getPublicKey(normalizedPrivateKey);
332
- case "p256":
333
- return p256.getPublicKey(normalizedPrivateKey);
334
- case "ed25519":
335
- return ed25519.getPublicKey(normalizedPrivateKey);
336
- default:
337
- throw new Error(`Unsupported curve: ${curve}`);
338
- }
339
- };
340
- function normalizeBytes(input) {
341
- if (input instanceof Uint8Array) {
342
- return input;
343
- }
344
- if (typeof input === "string") {
345
- return hexToBytes(input);
346
- }
347
- throw new Error("Invalid input format - expected Uint8Array or hex string");
341
+ function cidDecode(value) {
342
+ const parsed = CID.parse(value, MULTIBASE_DECODER);
343
+ return {
344
+ version: parsed.version,
345
+ codec: MULTICODEC_NAMES.get(parsed.code) ?? parsed.code,
346
+ hashCode: MULTIHASH_NAMES.get(parsed.multihash.code) ?? parsed.multihash.code,
347
+ digest: parsed.multihash.digest
348
+ };
348
349
  }
349
- function detectSignatureFormat(signature, curve) {
350
- const length = signature.length;
351
- if (curve === "ed25519") {
352
- return "raw";
350
+ var SD_LEAF_DOMAIN_V1 = "optimystic/sd-leaf/v1";
351
+ var SD_SET_DOMAIN_V1 = "optimystic/sd-set/v1";
352
+ var HIDDEN_ENCODING = "base64url";
353
+ function compareBytes(a, b) {
354
+ const len = Math.min(a.length, b.length);
355
+ for (let i = 0; i < len; i++) {
356
+ const d = a[i] - b[i];
357
+ if (d !== 0) return d;
358
+ }
359
+ return a.length - b.length;
360
+ }
361
+ function bytesEqual(a, b) {
362
+ if (a.length !== b.length) return false;
363
+ for (let i = 0; i < a.length; i++) {
364
+ if (a[i] !== b[i]) return false;
353
365
  }
354
- if (length === 64) {
355
- return "compact";
366
+ return true;
367
+ }
368
+ function requireSaltBytes(leaf) {
369
+ const { salt } = leaf;
370
+ if (salt == null) {
371
+ throw new Error(`set commitment: leaf '${leaf.name}' is missing a salt (an unsalted leaf is brute-forceable)`);
356
372
  }
357
- if (length >= 70 && length <= 72 && signature[0] === 48) {
358
- return "der";
373
+ const bytes = salt instanceof Uint8Array ? salt : fromString(salt, HIDDEN_ENCODING);
374
+ if (bytes.length === 0) {
375
+ throw new Error(`set commitment: leaf '${leaf.name}' has an empty salt (an unsalted leaf is brute-forceable)`);
359
376
  }
360
- return "compact";
377
+ return bytes;
361
378
  }
362
- function parseSignature(signature, format, curve) {
363
- if (curve === "ed25519") {
364
- return signature;
379
+ function assertUniqueNames(leaves) {
380
+ const seen = /* @__PURE__ */ new Set();
381
+ for (const leaf of leaves) {
382
+ if (seen.has(leaf.name)) {
383
+ throw new Error(`set commitment: duplicate leaf name '${leaf.name}'`);
384
+ }
385
+ seen.add(leaf.name);
365
386
  }
366
- const sigFormat = format === "raw" ? "compact" : format;
367
- if (curve === "secp256k1") {
368
- return secp256k1.Signature.fromBytes(signature, sigFormat).toBytes();
369
- } else if (curve === "p256") {
370
- return p256.Signature.fromBytes(signature, sigFormat).toBytes();
387
+ }
388
+ function leafDigest(leaf, hasher) {
389
+ const saltBytes = requireSaltBytes(leaf);
390
+ return hasher(encodeFields([SD_LEAF_DOMAIN_V1, leaf.name, leaf.value, saltBytes]));
391
+ }
392
+ function setCommit(leaves, hasher = resolveHasher("sha256"), encode = resolveOutputEncoder("base64url")) {
393
+ assertUniqueNames(leaves);
394
+ const leafDigests = leaves.map((leaf) => leafDigest(leaf, hasher));
395
+ leafDigests.sort(compareBytes);
396
+ return encode(hasher(encodeFields([SD_SET_DOMAIN_V1, ...leafDigests])));
397
+ }
398
+ function setDisclose(leaves, revealNames, hasher = resolveHasher("sha256")) {
399
+ assertUniqueNames(leaves);
400
+ const reveal = new Set(revealNames);
401
+ const disclosed = [];
402
+ const hidden = [];
403
+ for (const leaf of leaves) {
404
+ if (reveal.has(leaf.name)) {
405
+ disclosed.push(leaf);
406
+ } else {
407
+ hidden.push(toString(leafDigest(leaf, hasher), HIDDEN_ENCODING));
408
+ }
371
409
  }
372
- throw new Error(`Failed to parse signature for curve ${curve} with format ${format}`);
410
+ return { disclosed, hidden };
373
411
  }
374
- function SignatureValid(digest2, signature, publicKey, options = {}) {
412
+ function setVerify(root, disclosure, hasher = resolveHasher("sha256"), encode = resolveOutputEncoder("base64url")) {
375
413
  try {
376
- const {
377
- curve = "secp256k1",
378
- signatureFormat,
379
- allowMalleableSignatures
380
- } = options;
381
- const normalizedDigest = normalizeBytes(digest2);
382
- const normalizedSignature = normalizeBytes(signature);
383
- const normalizedPublicKey = normalizeBytes(publicKey);
384
- const detectedFormat = signatureFormat || detectSignatureFormat(normalizedSignature, curve);
385
- const parsedSignature = parseSignature(normalizedSignature, detectedFormat, curve);
386
- const verifyOptions = {};
387
- if (curve !== "ed25519" && allowMalleableSignatures !== void 0) {
388
- verifyOptions.lowS = !allowMalleableSignatures;
414
+ const { disclosed, hidden } = disclosure;
415
+ const digests = [];
416
+ for (const leaf of disclosed) {
417
+ digests.push(leafDigest(leaf, hasher));
389
418
  }
390
- switch (curve) {
391
- case "secp256k1":
392
- return secp256k1.verify(parsedSignature, normalizedDigest, normalizedPublicKey, verifyOptions);
393
- case "p256":
394
- return p256.verify(parsedSignature, normalizedDigest, normalizedPublicKey, verifyOptions);
395
- case "ed25519":
396
- return ed25519.verify(parsedSignature, normalizedDigest, normalizedPublicKey);
397
- default:
398
- throw new Error(`Unsupported curve: ${curve}`);
419
+ for (const h of hidden) {
420
+ digests.push(fromString(h, HIDDEN_ENCODING));
399
421
  }
400
- } catch (error) {
422
+ digests.sort(compareBytes);
423
+ const recomputed = hasher(encodeFields([SD_SET_DOMAIN_V1, ...digests]));
424
+ if (root instanceof Uint8Array) {
425
+ return bytesEqual(recomputed, root);
426
+ }
427
+ const encoded = encode(recomputed);
428
+ return typeof encoded === "string" && encoded === root;
429
+ } catch {
401
430
  return false;
402
431
  }
403
432
  }
404
- SignatureValid.secp256k1 = (digest2, signature, publicKey, options = {}) => {
405
- return SignatureValid(digest2, signature, publicKey, { ...options, curve: "secp256k1" });
406
- };
407
- SignatureValid.p256 = (digest2, signature, publicKey, options = {}) => {
408
- return SignatureValid(digest2, signature, publicKey, { ...options, curve: "p256" });
409
- };
410
- SignatureValid.ed25519 = (digest2, signature, publicKey, options = {}) => {
411
- return SignatureValid(digest2, signature, publicKey, { ...options, curve: "ed25519" });
412
- };
413
- SignatureValid.batch = (verifications) => {
414
- return verifications.map(
415
- ({ digest: digest2, signature, publicKey, options }) => SignatureValid(digest2, signature, publicKey, options)
416
- );
417
- };
418
- SignatureValid.detailed = (digest2, signature, publicKey, options = {}) => {
419
- const curve = options.curve || "secp256k1";
420
- try {
421
- const normalizedSignature = normalizeBytes(signature);
422
- const detectedFormat = options.signatureFormat || detectSignatureFormat(normalizedSignature, curve);
423
- const valid = SignatureValid(digest2, signature, publicKey, options);
424
- return {
425
- valid,
426
- curve,
427
- signatureFormat: detectedFormat
428
- };
429
- } catch (error) {
430
- return {
431
- valid: false,
432
- curve,
433
- signatureFormat: "unknown",
434
- error: error instanceof Error ? error.message : "Unknown error"
435
- };
436
- }
437
- };
438
433
 
439
- export { Digest, Sign, SignatureValid, digest, generatePrivateKey, getPublicKey, hashMod, randomBytes, sign, verify };
434
+ export { cid, cidDecode, cidV1, digest, digestFields, encodeFields, generatePrivateKey, getPublicKey, hashMod, leafDigest, randomBytes, resolveHasher, resolveOutputEncoder, setCommit, setDisclose, setVerify, sign, verify };
440
435
  //# sourceMappingURL=index.js.map
441
436
  //# sourceMappingURL=index.js.map