@motebit/verify 0.5.3 → 0.6.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/README.md +1 -1
- package/dist/index.d.ts +20 -20
- package/dist/index.js +1419 -713
- package/package.json +17 -14
package/dist/index.js
CHANGED
|
@@ -1,769 +1,1475 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
1
|
+
// ../../node_modules/.pnpm/@noble+ed25519@3.0.0/node_modules/@noble/ed25519/index.js
|
|
2
|
+
var ed25519_CURVE = {
|
|
3
|
+
p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
|
|
4
|
+
n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,
|
|
5
|
+
h: 8n,
|
|
6
|
+
a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,
|
|
7
|
+
d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,
|
|
8
|
+
Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,
|
|
9
|
+
Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n
|
|
10
|
+
};
|
|
11
|
+
var { p: P, n: N, Gx, Gy, a: _a, d: _d, h } = ed25519_CURVE;
|
|
12
|
+
var L = 32;
|
|
13
|
+
var L2 = 64;
|
|
14
|
+
var captureTrace = (...args) => {
|
|
15
|
+
if ("captureStackTrace" in Error && typeof Error.captureStackTrace === "function") {
|
|
16
|
+
Error.captureStackTrace(...args);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var err = (message = "") => {
|
|
20
|
+
const e = new Error(message);
|
|
21
|
+
captureTrace(e, err);
|
|
22
|
+
throw e;
|
|
23
|
+
};
|
|
24
|
+
var isBig = (n) => typeof n === "bigint";
|
|
25
|
+
var isStr = (s) => typeof s === "string";
|
|
26
|
+
var isBytes = (a) => a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
27
|
+
var abytes = (value, length, title = "") => {
|
|
28
|
+
const bytes = isBytes(value);
|
|
29
|
+
const len = value?.length;
|
|
30
|
+
const needsLen = length !== void 0;
|
|
31
|
+
if (!bytes || needsLen && len !== length) {
|
|
32
|
+
const prefix = title && `"${title}" `;
|
|
33
|
+
const ofLen = needsLen ? ` of length ${length}` : "";
|
|
34
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
35
|
+
err(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
};
|
|
39
|
+
var u8n = (len) => new Uint8Array(len);
|
|
40
|
+
var u8fr = (buf) => Uint8Array.from(buf);
|
|
41
|
+
var padh = (n, pad) => n.toString(16).padStart(pad, "0");
|
|
42
|
+
var bytesToHex = (b) => Array.from(abytes(b)).map((e) => padh(e, 2)).join("");
|
|
43
|
+
var C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
|
44
|
+
var _ch = (ch) => {
|
|
45
|
+
if (ch >= C._0 && ch <= C._9)
|
|
46
|
+
return ch - C._0;
|
|
47
|
+
if (ch >= C.A && ch <= C.F)
|
|
48
|
+
return ch - (C.A - 10);
|
|
49
|
+
if (ch >= C.a && ch <= C.f)
|
|
50
|
+
return ch - (C.a - 10);
|
|
51
|
+
return;
|
|
52
|
+
};
|
|
53
|
+
var hexToBytes = (hex) => {
|
|
54
|
+
const e = "hex invalid";
|
|
55
|
+
if (!isStr(hex))
|
|
56
|
+
return err(e);
|
|
57
|
+
const hl = hex.length;
|
|
58
|
+
const al = hl / 2;
|
|
59
|
+
if (hl % 2)
|
|
60
|
+
return err(e);
|
|
61
|
+
const array = u8n(al);
|
|
62
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
|
63
|
+
const n1 = _ch(hex.charCodeAt(hi));
|
|
64
|
+
const n2 = _ch(hex.charCodeAt(hi + 1));
|
|
65
|
+
if (n1 === void 0 || n2 === void 0)
|
|
66
|
+
return err(e);
|
|
67
|
+
array[ai] = n1 * 16 + n2;
|
|
68
|
+
}
|
|
69
|
+
return array;
|
|
70
|
+
};
|
|
71
|
+
var cr = () => globalThis?.crypto;
|
|
72
|
+
var subtle = () => cr()?.subtle ?? err("crypto.subtle must be defined, consider polyfill");
|
|
73
|
+
var concatBytes = (...arrs) => {
|
|
74
|
+
const r = u8n(arrs.reduce((sum, a) => sum + abytes(a).length, 0));
|
|
75
|
+
let pad = 0;
|
|
76
|
+
arrs.forEach((a) => {
|
|
77
|
+
r.set(a, pad);
|
|
78
|
+
pad += a.length;
|
|
79
|
+
});
|
|
80
|
+
return r;
|
|
81
|
+
};
|
|
82
|
+
var big = BigInt;
|
|
83
|
+
var assertRange = (n, min, max, msg = "bad number: out of range") => isBig(n) && min <= n && n < max ? n : err(msg);
|
|
84
|
+
var M = (a, b = P) => {
|
|
85
|
+
const r = a % b;
|
|
86
|
+
return r >= 0n ? r : b + r;
|
|
87
|
+
};
|
|
88
|
+
var modN = (a) => M(a, N);
|
|
89
|
+
var invert = (num, md) => {
|
|
90
|
+
if (num === 0n || md <= 0n)
|
|
91
|
+
err("no inverse n=" + num + " mod=" + md);
|
|
92
|
+
let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
|
|
93
|
+
while (a !== 0n) {
|
|
94
|
+
const q = b / a, r = b % a;
|
|
95
|
+
const m = x - u * q, n = y - v * q;
|
|
96
|
+
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
97
|
+
}
|
|
98
|
+
return b === 1n ? M(x, md) : err("no inverse");
|
|
99
|
+
};
|
|
100
|
+
var apoint = (p) => p instanceof Point ? p : err("Point expected");
|
|
101
|
+
var B256 = 2n ** 256n;
|
|
102
|
+
var Point = class _Point {
|
|
103
|
+
static BASE;
|
|
104
|
+
static ZERO;
|
|
105
|
+
X;
|
|
106
|
+
Y;
|
|
107
|
+
Z;
|
|
108
|
+
T;
|
|
109
|
+
constructor(X, Y, Z, T) {
|
|
110
|
+
const max = B256;
|
|
111
|
+
this.X = assertRange(X, 0n, max);
|
|
112
|
+
this.Y = assertRange(Y, 0n, max);
|
|
113
|
+
this.Z = assertRange(Z, 1n, max);
|
|
114
|
+
this.T = assertRange(T, 0n, max);
|
|
115
|
+
Object.freeze(this);
|
|
116
|
+
}
|
|
117
|
+
static CURVE() {
|
|
118
|
+
return ed25519_CURVE;
|
|
119
|
+
}
|
|
120
|
+
static fromAffine(p) {
|
|
121
|
+
return new _Point(p.x, p.y, 1n, M(p.x * p.y));
|
|
122
|
+
}
|
|
123
|
+
/** RFC8032 5.1.3: Uint8Array to Point. */
|
|
124
|
+
static fromBytes(hex, zip215 = false) {
|
|
125
|
+
const d = _d;
|
|
126
|
+
const normed = u8fr(abytes(hex, L));
|
|
127
|
+
const lastByte = hex[31];
|
|
128
|
+
normed[31] = lastByte & ~128;
|
|
129
|
+
const y = bytesToNumLE(normed);
|
|
130
|
+
const max = zip215 ? B256 : P;
|
|
131
|
+
assertRange(y, 0n, max);
|
|
132
|
+
const y2 = M(y * y);
|
|
133
|
+
const u = M(y2 - 1n);
|
|
134
|
+
const v = M(d * y2 + 1n);
|
|
135
|
+
let { isValid, value: x } = uvRatio(u, v);
|
|
136
|
+
if (!isValid)
|
|
137
|
+
err("bad point: y not sqrt");
|
|
138
|
+
const isXOdd = (x & 1n) === 1n;
|
|
139
|
+
const isLastByteOdd = (lastByte & 128) !== 0;
|
|
140
|
+
if (!zip215 && x === 0n && isLastByteOdd)
|
|
141
|
+
err("bad point: x==0, isLastByteOdd");
|
|
142
|
+
if (isLastByteOdd !== isXOdd)
|
|
143
|
+
x = M(-x);
|
|
144
|
+
return new _Point(x, y, 1n, M(x * y));
|
|
145
|
+
}
|
|
146
|
+
static fromHex(hex, zip215) {
|
|
147
|
+
return _Point.fromBytes(hexToBytes(hex), zip215);
|
|
148
|
+
}
|
|
149
|
+
get x() {
|
|
150
|
+
return this.toAffine().x;
|
|
151
|
+
}
|
|
152
|
+
get y() {
|
|
153
|
+
return this.toAffine().y;
|
|
154
|
+
}
|
|
155
|
+
/** Checks if the point is valid and on-curve. */
|
|
156
|
+
assertValidity() {
|
|
157
|
+
const a = _a;
|
|
158
|
+
const d = _d;
|
|
159
|
+
const p = this;
|
|
160
|
+
if (p.is0())
|
|
161
|
+
return err("bad point: ZERO");
|
|
162
|
+
const { X, Y, Z, T } = p;
|
|
163
|
+
const X2 = M(X * X);
|
|
164
|
+
const Y2 = M(Y * Y);
|
|
165
|
+
const Z2 = M(Z * Z);
|
|
166
|
+
const Z4 = M(Z2 * Z2);
|
|
167
|
+
const aX2 = M(X2 * a);
|
|
168
|
+
const left = M(Z2 * M(aX2 + Y2));
|
|
169
|
+
const right = M(Z4 + M(d * M(X2 * Y2)));
|
|
170
|
+
if (left !== right)
|
|
171
|
+
return err("bad point: equation left != right (1)");
|
|
172
|
+
const XY = M(X * Y);
|
|
173
|
+
const ZT = M(Z * T);
|
|
174
|
+
if (XY !== ZT)
|
|
175
|
+
return err("bad point: equation left != right (2)");
|
|
176
|
+
return this;
|
|
177
|
+
}
|
|
178
|
+
/** Equality check: compare points P&Q. */
|
|
179
|
+
equals(other) {
|
|
180
|
+
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
181
|
+
const { X: X2, Y: Y2, Z: Z2 } = apoint(other);
|
|
182
|
+
const X1Z2 = M(X1 * Z2);
|
|
183
|
+
const X2Z1 = M(X2 * Z1);
|
|
184
|
+
const Y1Z2 = M(Y1 * Z2);
|
|
185
|
+
const Y2Z1 = M(Y2 * Z1);
|
|
186
|
+
return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
|
|
187
|
+
}
|
|
188
|
+
is0() {
|
|
189
|
+
return this.equals(I);
|
|
190
|
+
}
|
|
191
|
+
/** Flip point over y coordinate. */
|
|
192
|
+
negate() {
|
|
193
|
+
return new _Point(M(-this.X), this.Y, this.Z, M(-this.T));
|
|
194
|
+
}
|
|
195
|
+
/** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */
|
|
196
|
+
double() {
|
|
197
|
+
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
198
|
+
const a = _a;
|
|
199
|
+
const A = M(X1 * X1);
|
|
200
|
+
const B = M(Y1 * Y1);
|
|
201
|
+
const C2 = M(2n * M(Z1 * Z1));
|
|
202
|
+
const D = M(a * A);
|
|
203
|
+
const x1y1 = X1 + Y1;
|
|
204
|
+
const E = M(M(x1y1 * x1y1) - A - B);
|
|
205
|
+
const G2 = D + B;
|
|
206
|
+
const F = G2 - C2;
|
|
207
|
+
const H = D - B;
|
|
208
|
+
const X3 = M(E * F);
|
|
209
|
+
const Y3 = M(G2 * H);
|
|
210
|
+
const T3 = M(E * H);
|
|
211
|
+
const Z3 = M(F * G2);
|
|
212
|
+
return new _Point(X3, Y3, Z3, T3);
|
|
213
|
+
}
|
|
214
|
+
/** Point addition. Complete formula. Cost: `8M + 1*k + 8add + 1*2`. */
|
|
215
|
+
add(other) {
|
|
216
|
+
const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;
|
|
217
|
+
const { X: X2, Y: Y2, Z: Z2, T: T2 } = apoint(other);
|
|
218
|
+
const a = _a;
|
|
219
|
+
const d = _d;
|
|
220
|
+
const A = M(X1 * X2);
|
|
221
|
+
const B = M(Y1 * Y2);
|
|
222
|
+
const C2 = M(T1 * d * T2);
|
|
223
|
+
const D = M(Z1 * Z2);
|
|
224
|
+
const E = M((X1 + Y1) * (X2 + Y2) - A - B);
|
|
225
|
+
const F = M(D - C2);
|
|
226
|
+
const G2 = M(D + C2);
|
|
227
|
+
const H = M(B - a * A);
|
|
228
|
+
const X3 = M(E * F);
|
|
229
|
+
const Y3 = M(G2 * H);
|
|
230
|
+
const T3 = M(E * H);
|
|
231
|
+
const Z3 = M(F * G2);
|
|
232
|
+
return new _Point(X3, Y3, Z3, T3);
|
|
233
|
+
}
|
|
234
|
+
subtract(other) {
|
|
235
|
+
return this.add(apoint(other).negate());
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.
|
|
239
|
+
* Uses {@link wNAF} for base point.
|
|
240
|
+
* Uses fake point to mitigate side-channel leakage.
|
|
241
|
+
* @param n scalar by which point is multiplied
|
|
242
|
+
* @param safe safe mode guards against timing attacks; unsafe mode is faster
|
|
243
|
+
*/
|
|
244
|
+
multiply(n, safe = true) {
|
|
245
|
+
if (!safe && (n === 0n || this.is0()))
|
|
246
|
+
return I;
|
|
247
|
+
assertRange(n, 1n, N);
|
|
248
|
+
if (n === 1n)
|
|
249
|
+
return this;
|
|
250
|
+
if (this.equals(G))
|
|
251
|
+
return wNAF(n).p;
|
|
252
|
+
let p = I;
|
|
253
|
+
let f = G;
|
|
254
|
+
for (let d = this; n > 0n; d = d.double(), n >>= 1n) {
|
|
255
|
+
if (n & 1n)
|
|
256
|
+
p = p.add(d);
|
|
257
|
+
else if (safe)
|
|
258
|
+
f = f.add(d);
|
|
259
|
+
}
|
|
260
|
+
return p;
|
|
261
|
+
}
|
|
262
|
+
multiplyUnsafe(scalar) {
|
|
263
|
+
return this.multiply(scalar, false);
|
|
264
|
+
}
|
|
265
|
+
/** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */
|
|
266
|
+
toAffine() {
|
|
267
|
+
const { X, Y, Z } = this;
|
|
268
|
+
if (this.equals(I))
|
|
269
|
+
return { x: 0n, y: 1n };
|
|
270
|
+
const iz = invert(Z, P);
|
|
271
|
+
if (M(Z * iz) !== 1n)
|
|
272
|
+
err("invalid inverse");
|
|
273
|
+
const x = M(X * iz);
|
|
274
|
+
const y = M(Y * iz);
|
|
275
|
+
return { x, y };
|
|
276
|
+
}
|
|
277
|
+
toBytes() {
|
|
278
|
+
const { x, y } = this.assertValidity().toAffine();
|
|
279
|
+
const b = numTo32bLE(y);
|
|
280
|
+
b[31] |= x & 1n ? 128 : 0;
|
|
281
|
+
return b;
|
|
282
|
+
}
|
|
283
|
+
toHex() {
|
|
284
|
+
return bytesToHex(this.toBytes());
|
|
285
|
+
}
|
|
286
|
+
clearCofactor() {
|
|
287
|
+
return this.multiply(big(h), false);
|
|
288
|
+
}
|
|
289
|
+
isSmallOrder() {
|
|
290
|
+
return this.clearCofactor().is0();
|
|
291
|
+
}
|
|
292
|
+
isTorsionFree() {
|
|
293
|
+
let p = this.multiply(N / 2n, false).double();
|
|
294
|
+
if (N % 2n)
|
|
295
|
+
p = p.add(this);
|
|
296
|
+
return p.is0();
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
var G = new Point(Gx, Gy, 1n, M(Gx * Gy));
|
|
300
|
+
var I = new Point(0n, 1n, 1n, 0n);
|
|
301
|
+
Point.BASE = G;
|
|
302
|
+
Point.ZERO = I;
|
|
303
|
+
var numTo32bLE = (num) => hexToBytes(padh(assertRange(num, 0n, B256), L2)).reverse();
|
|
304
|
+
var bytesToNumLE = (b) => big("0x" + bytesToHex(u8fr(abytes(b)).reverse()));
|
|
305
|
+
var pow2 = (x, power) => {
|
|
306
|
+
let r = x;
|
|
307
|
+
while (power-- > 0n) {
|
|
308
|
+
r *= r;
|
|
309
|
+
r %= P;
|
|
310
|
+
}
|
|
311
|
+
return r;
|
|
312
|
+
};
|
|
313
|
+
var pow_2_252_3 = (x) => {
|
|
314
|
+
const x2 = x * x % P;
|
|
315
|
+
const b2 = x2 * x % P;
|
|
316
|
+
const b4 = pow2(b2, 2n) * b2 % P;
|
|
317
|
+
const b5 = pow2(b4, 1n) * x % P;
|
|
318
|
+
const b10 = pow2(b5, 5n) * b5 % P;
|
|
319
|
+
const b20 = pow2(b10, 10n) * b10 % P;
|
|
320
|
+
const b40 = pow2(b20, 20n) * b20 % P;
|
|
321
|
+
const b80 = pow2(b40, 40n) * b40 % P;
|
|
322
|
+
const b160 = pow2(b80, 80n) * b80 % P;
|
|
323
|
+
const b240 = pow2(b160, 80n) * b80 % P;
|
|
324
|
+
const b250 = pow2(b240, 10n) * b10 % P;
|
|
325
|
+
const pow_p_5_8 = pow2(b250, 2n) * x % P;
|
|
326
|
+
return { pow_p_5_8, b2 };
|
|
327
|
+
};
|
|
328
|
+
var RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n;
|
|
329
|
+
var uvRatio = (u, v) => {
|
|
330
|
+
const v3 = M(v * v * v);
|
|
331
|
+
const v7 = M(v3 * v3 * v);
|
|
332
|
+
const pow = pow_2_252_3(u * v7).pow_p_5_8;
|
|
333
|
+
let x = M(u * v3 * pow);
|
|
334
|
+
const vx2 = M(v * x * x);
|
|
335
|
+
const root1 = x;
|
|
336
|
+
const root2 = M(x * RM1);
|
|
337
|
+
const useRoot1 = vx2 === u;
|
|
338
|
+
const useRoot2 = vx2 === M(-u);
|
|
339
|
+
const noRoot = vx2 === M(-u * RM1);
|
|
340
|
+
if (useRoot1)
|
|
341
|
+
x = root1;
|
|
342
|
+
if (useRoot2 || noRoot)
|
|
343
|
+
x = root2;
|
|
344
|
+
if ((M(x) & 1n) === 1n)
|
|
345
|
+
x = M(-x);
|
|
346
|
+
return { isValid: useRoot1 || useRoot2, value: x };
|
|
347
|
+
};
|
|
348
|
+
var modL_LE = (hash) => modN(bytesToNumLE(hash));
|
|
349
|
+
var sha512a = (...m) => hashes.sha512Async(concatBytes(...m));
|
|
350
|
+
var hashFinishA = (res) => sha512a(res.hashable).then(res.finish);
|
|
351
|
+
var defaultVerifyOpts = { zip215: true };
|
|
352
|
+
var _verify = (sig, msg, pub, opts = defaultVerifyOpts) => {
|
|
353
|
+
sig = abytes(sig, L2);
|
|
354
|
+
msg = abytes(msg);
|
|
355
|
+
pub = abytes(pub, L);
|
|
356
|
+
const { zip215 } = opts;
|
|
357
|
+
let A;
|
|
358
|
+
let R;
|
|
359
|
+
let s;
|
|
360
|
+
let SB;
|
|
361
|
+
let hashable = Uint8Array.of();
|
|
362
|
+
try {
|
|
363
|
+
A = Point.fromBytes(pub, zip215);
|
|
364
|
+
R = Point.fromBytes(sig.slice(0, L), zip215);
|
|
365
|
+
s = bytesToNumLE(sig.slice(L, L2));
|
|
366
|
+
SB = G.multiply(s, false);
|
|
367
|
+
hashable = concatBytes(R.toBytes(), A.toBytes(), msg);
|
|
368
|
+
} catch (error) {
|
|
369
|
+
}
|
|
370
|
+
const finish = (hashed) => {
|
|
371
|
+
if (SB == null)
|
|
372
|
+
return false;
|
|
373
|
+
if (!zip215 && A.isSmallOrder())
|
|
374
|
+
return false;
|
|
375
|
+
const k = modL_LE(hashed);
|
|
376
|
+
const RkA = R.add(A.multiply(k, false));
|
|
377
|
+
return RkA.add(SB.negate()).clearCofactor().is0();
|
|
378
|
+
};
|
|
379
|
+
return { hashable, finish };
|
|
380
|
+
};
|
|
381
|
+
var verifyAsync = async (signature, message, publicKey, opts = defaultVerifyOpts) => hashFinishA(_verify(signature, message, publicKey, opts));
|
|
382
|
+
var hashes = {
|
|
383
|
+
sha512Async: async (message) => {
|
|
384
|
+
const s = subtle();
|
|
385
|
+
const m = concatBytes(message);
|
|
386
|
+
return u8n(await s.digest("SHA-512", m.buffer));
|
|
387
|
+
},
|
|
388
|
+
sha512: void 0
|
|
389
|
+
};
|
|
390
|
+
var W = 8;
|
|
391
|
+
var scalarBits = 256;
|
|
392
|
+
var pwindows = Math.ceil(scalarBits / W) + 1;
|
|
393
|
+
var pwindowSize = 2 ** (W - 1);
|
|
394
|
+
var precompute = () => {
|
|
395
|
+
const points = [];
|
|
396
|
+
let p = G;
|
|
397
|
+
let b = p;
|
|
398
|
+
for (let w = 0; w < pwindows; w++) {
|
|
399
|
+
b = p;
|
|
400
|
+
points.push(b);
|
|
401
|
+
for (let i = 1; i < pwindowSize; i++) {
|
|
402
|
+
b = b.add(p);
|
|
403
|
+
points.push(b);
|
|
404
|
+
}
|
|
405
|
+
p = b.double();
|
|
406
|
+
}
|
|
407
|
+
return points;
|
|
408
|
+
};
|
|
409
|
+
var Gpows = void 0;
|
|
410
|
+
var ctneg = (cnd, p) => {
|
|
411
|
+
const n = p.negate();
|
|
412
|
+
return cnd ? n : p;
|
|
413
|
+
};
|
|
414
|
+
var wNAF = (n) => {
|
|
415
|
+
const comp = Gpows || (Gpows = precompute());
|
|
416
|
+
let p = I;
|
|
417
|
+
let f = G;
|
|
418
|
+
const pow_2_w = 2 ** W;
|
|
419
|
+
const maxNum = pow_2_w;
|
|
420
|
+
const mask = big(pow_2_w - 1);
|
|
421
|
+
const shiftBy = big(W);
|
|
422
|
+
for (let w = 0; w < pwindows; w++) {
|
|
423
|
+
let wbits = Number(n & mask);
|
|
424
|
+
n >>= shiftBy;
|
|
425
|
+
if (wbits > pwindowSize) {
|
|
426
|
+
wbits -= maxNum;
|
|
427
|
+
n += 1n;
|
|
428
|
+
}
|
|
429
|
+
const off = w * pwindowSize;
|
|
430
|
+
const offF = off;
|
|
431
|
+
const offP = off + Math.abs(wbits) - 1;
|
|
432
|
+
const isEven = w % 2 !== 0;
|
|
433
|
+
const isNeg = wbits < 0;
|
|
434
|
+
if (wbits === 0) {
|
|
435
|
+
f = f.add(ctneg(isEven, comp[offF]));
|
|
436
|
+
} else {
|
|
437
|
+
p = p.add(ctneg(isNeg, comp[offP]));
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (n !== 0n)
|
|
441
|
+
err("invalid wnaf");
|
|
442
|
+
return { p, f };
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/utils.js
|
|
446
|
+
function isBytes2(a) {
|
|
447
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
448
|
+
}
|
|
449
|
+
function abytes2(b, ...lengths) {
|
|
450
|
+
if (!isBytes2(b))
|
|
451
|
+
throw new Error("Uint8Array expected");
|
|
452
|
+
if (lengths.length > 0 && !lengths.includes(b.length))
|
|
453
|
+
throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
|
|
454
|
+
}
|
|
455
|
+
function aexists(instance, checkFinished = true) {
|
|
456
|
+
if (instance.destroyed)
|
|
457
|
+
throw new Error("Hash instance has been destroyed");
|
|
458
|
+
if (checkFinished && instance.finished)
|
|
459
|
+
throw new Error("Hash#digest() has already been called");
|
|
460
|
+
}
|
|
461
|
+
function aoutput(out, instance) {
|
|
462
|
+
abytes2(out);
|
|
463
|
+
const min = instance.outputLen;
|
|
464
|
+
if (out.length < min) {
|
|
465
|
+
throw new Error("digestInto() expects output buffer of length at least " + min);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
function clean(...arrays) {
|
|
469
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
470
|
+
arrays[i].fill(0);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
function createView(arr) {
|
|
474
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
475
|
+
}
|
|
476
|
+
function utf8ToBytes(str) {
|
|
477
|
+
if (typeof str !== "string")
|
|
478
|
+
throw new Error("string expected");
|
|
479
|
+
return new Uint8Array(new TextEncoder().encode(str));
|
|
480
|
+
}
|
|
481
|
+
function toBytes(data) {
|
|
482
|
+
if (typeof data === "string")
|
|
483
|
+
data = utf8ToBytes(data);
|
|
484
|
+
abytes2(data);
|
|
485
|
+
return data;
|
|
486
|
+
}
|
|
487
|
+
var Hash = class {
|
|
488
|
+
};
|
|
489
|
+
function createHasher(hashCons) {
|
|
490
|
+
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
|
|
491
|
+
const tmp = hashCons();
|
|
492
|
+
hashC.outputLen = tmp.outputLen;
|
|
493
|
+
hashC.blockLen = tmp.blockLen;
|
|
494
|
+
hashC.create = () => hashCons();
|
|
495
|
+
return hashC;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/_md.js
|
|
499
|
+
function setBigUint64(view, byteOffset, value, isLE) {
|
|
500
|
+
if (typeof view.setBigUint64 === "function")
|
|
501
|
+
return view.setBigUint64(byteOffset, value, isLE);
|
|
502
|
+
const _32n2 = BigInt(32);
|
|
503
|
+
const _u32_max = BigInt(4294967295);
|
|
504
|
+
const wh = Number(value >> _32n2 & _u32_max);
|
|
505
|
+
const wl = Number(value & _u32_max);
|
|
506
|
+
const h2 = isLE ? 4 : 0;
|
|
507
|
+
const l = isLE ? 0 : 4;
|
|
508
|
+
view.setUint32(byteOffset + h2, wh, isLE);
|
|
509
|
+
view.setUint32(byteOffset + l, wl, isLE);
|
|
510
|
+
}
|
|
511
|
+
var HashMD = class extends Hash {
|
|
512
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
513
|
+
super();
|
|
514
|
+
this.finished = false;
|
|
515
|
+
this.length = 0;
|
|
516
|
+
this.pos = 0;
|
|
517
|
+
this.destroyed = false;
|
|
518
|
+
this.blockLen = blockLen;
|
|
519
|
+
this.outputLen = outputLen;
|
|
520
|
+
this.padOffset = padOffset;
|
|
521
|
+
this.isLE = isLE;
|
|
522
|
+
this.buffer = new Uint8Array(blockLen);
|
|
523
|
+
this.view = createView(this.buffer);
|
|
524
|
+
}
|
|
525
|
+
update(data) {
|
|
526
|
+
aexists(this);
|
|
527
|
+
data = toBytes(data);
|
|
528
|
+
abytes2(data);
|
|
529
|
+
const { view, buffer, blockLen } = this;
|
|
530
|
+
const len = data.length;
|
|
531
|
+
for (let pos = 0; pos < len; ) {
|
|
532
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
533
|
+
if (take === blockLen) {
|
|
534
|
+
const dataView = createView(data);
|
|
535
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
536
|
+
this.process(dataView, pos);
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
540
|
+
this.pos += take;
|
|
541
|
+
pos += take;
|
|
542
|
+
if (this.pos === blockLen) {
|
|
543
|
+
this.process(view, 0);
|
|
544
|
+
this.pos = 0;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
this.length += data.length;
|
|
548
|
+
this.roundClean();
|
|
549
|
+
return this;
|
|
550
|
+
}
|
|
551
|
+
digestInto(out) {
|
|
552
|
+
aexists(this);
|
|
553
|
+
aoutput(out, this);
|
|
554
|
+
this.finished = true;
|
|
555
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
556
|
+
let { pos } = this;
|
|
557
|
+
buffer[pos++] = 128;
|
|
558
|
+
clean(this.buffer.subarray(pos));
|
|
559
|
+
if (this.padOffset > blockLen - pos) {
|
|
560
|
+
this.process(view, 0);
|
|
561
|
+
pos = 0;
|
|
562
|
+
}
|
|
563
|
+
for (let i = pos; i < blockLen; i++)
|
|
564
|
+
buffer[i] = 0;
|
|
565
|
+
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
|
|
566
|
+
this.process(view, 0);
|
|
567
|
+
const oview = createView(out);
|
|
568
|
+
const len = this.outputLen;
|
|
569
|
+
if (len % 4)
|
|
570
|
+
throw new Error("_sha2: outputLen should be aligned to 32bit");
|
|
571
|
+
const outLen = len / 4;
|
|
572
|
+
const state = this.get();
|
|
573
|
+
if (outLen > state.length)
|
|
574
|
+
throw new Error("_sha2: outputLen bigger than state");
|
|
575
|
+
for (let i = 0; i < outLen; i++)
|
|
576
|
+
oview.setUint32(4 * i, state[i], isLE);
|
|
577
|
+
}
|
|
578
|
+
digest() {
|
|
579
|
+
const { buffer, outputLen } = this;
|
|
580
|
+
this.digestInto(buffer);
|
|
581
|
+
const res = buffer.slice(0, outputLen);
|
|
582
|
+
this.destroy();
|
|
583
|
+
return res;
|
|
584
|
+
}
|
|
585
|
+
_cloneInto(to) {
|
|
586
|
+
to || (to = new this.constructor());
|
|
587
|
+
to.set(...this.get());
|
|
588
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
589
|
+
to.destroyed = destroyed;
|
|
590
|
+
to.finished = finished;
|
|
591
|
+
to.length = length;
|
|
592
|
+
to.pos = pos;
|
|
593
|
+
if (length % blockLen)
|
|
594
|
+
to.buffer.set(buffer);
|
|
595
|
+
return to;
|
|
596
|
+
}
|
|
597
|
+
clone() {
|
|
598
|
+
return this._cloneInto();
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
var SHA512_IV = /* @__PURE__ */ Uint32Array.from([
|
|
602
|
+
1779033703,
|
|
603
|
+
4089235720,
|
|
604
|
+
3144134277,
|
|
605
|
+
2227873595,
|
|
606
|
+
1013904242,
|
|
607
|
+
4271175723,
|
|
608
|
+
2773480762,
|
|
609
|
+
1595750129,
|
|
610
|
+
1359893119,
|
|
611
|
+
2917565137,
|
|
612
|
+
2600822924,
|
|
613
|
+
725511199,
|
|
614
|
+
528734635,
|
|
615
|
+
4215389547,
|
|
616
|
+
1541459225,
|
|
617
|
+
327033209
|
|
618
|
+
]);
|
|
619
|
+
|
|
620
|
+
// ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/_u64.js
|
|
621
|
+
var U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
|
|
622
|
+
var _32n = /* @__PURE__ */ BigInt(32);
|
|
623
|
+
function fromBig(n, le = false) {
|
|
624
|
+
if (le)
|
|
625
|
+
return { h: Number(n & U32_MASK64), l: Number(n >> _32n & U32_MASK64) };
|
|
626
|
+
return { h: Number(n >> _32n & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
|
|
627
|
+
}
|
|
628
|
+
function split(lst, le = false) {
|
|
629
|
+
const len = lst.length;
|
|
630
|
+
let Ah = new Uint32Array(len);
|
|
631
|
+
let Al = new Uint32Array(len);
|
|
632
|
+
for (let i = 0; i < len; i++) {
|
|
633
|
+
const { h: h2, l } = fromBig(lst[i], le);
|
|
634
|
+
[Ah[i], Al[i]] = [h2, l];
|
|
635
|
+
}
|
|
636
|
+
return [Ah, Al];
|
|
637
|
+
}
|
|
638
|
+
var shrSH = (h2, _l, s) => h2 >>> s;
|
|
639
|
+
var shrSL = (h2, l, s) => h2 << 32 - s | l >>> s;
|
|
640
|
+
var rotrSH = (h2, l, s) => h2 >>> s | l << 32 - s;
|
|
641
|
+
var rotrSL = (h2, l, s) => h2 << 32 - s | l >>> s;
|
|
642
|
+
var rotrBH = (h2, l, s) => h2 << 64 - s | l >>> s - 32;
|
|
643
|
+
var rotrBL = (h2, l, s) => h2 >>> s - 32 | l << 64 - s;
|
|
644
|
+
function add(Ah, Al, Bh, Bl) {
|
|
645
|
+
const l = (Al >>> 0) + (Bl >>> 0);
|
|
646
|
+
return { h: Ah + Bh + (l / 2 ** 32 | 0) | 0, l: l | 0 };
|
|
647
|
+
}
|
|
648
|
+
var add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
|
|
649
|
+
var add3H = (low, Ah, Bh, Ch) => Ah + Bh + Ch + (low / 2 ** 32 | 0) | 0;
|
|
650
|
+
var add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
|
|
651
|
+
var add4H = (low, Ah, Bh, Ch, Dh) => Ah + Bh + Ch + Dh + (low / 2 ** 32 | 0) | 0;
|
|
652
|
+
var add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
|
|
653
|
+
var add5H = (low, Ah, Bh, Ch, Dh, Eh) => Ah + Bh + Ch + Dh + Eh + (low / 2 ** 32 | 0) | 0;
|
|
654
|
+
|
|
655
|
+
// ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha2.js
|
|
656
|
+
var K512 = /* @__PURE__ */ (() => split([
|
|
657
|
+
"0x428a2f98d728ae22",
|
|
658
|
+
"0x7137449123ef65cd",
|
|
659
|
+
"0xb5c0fbcfec4d3b2f",
|
|
660
|
+
"0xe9b5dba58189dbbc",
|
|
661
|
+
"0x3956c25bf348b538",
|
|
662
|
+
"0x59f111f1b605d019",
|
|
663
|
+
"0x923f82a4af194f9b",
|
|
664
|
+
"0xab1c5ed5da6d8118",
|
|
665
|
+
"0xd807aa98a3030242",
|
|
666
|
+
"0x12835b0145706fbe",
|
|
667
|
+
"0x243185be4ee4b28c",
|
|
668
|
+
"0x550c7dc3d5ffb4e2",
|
|
669
|
+
"0x72be5d74f27b896f",
|
|
670
|
+
"0x80deb1fe3b1696b1",
|
|
671
|
+
"0x9bdc06a725c71235",
|
|
672
|
+
"0xc19bf174cf692694",
|
|
673
|
+
"0xe49b69c19ef14ad2",
|
|
674
|
+
"0xefbe4786384f25e3",
|
|
675
|
+
"0x0fc19dc68b8cd5b5",
|
|
676
|
+
"0x240ca1cc77ac9c65",
|
|
677
|
+
"0x2de92c6f592b0275",
|
|
678
|
+
"0x4a7484aa6ea6e483",
|
|
679
|
+
"0x5cb0a9dcbd41fbd4",
|
|
680
|
+
"0x76f988da831153b5",
|
|
681
|
+
"0x983e5152ee66dfab",
|
|
682
|
+
"0xa831c66d2db43210",
|
|
683
|
+
"0xb00327c898fb213f",
|
|
684
|
+
"0xbf597fc7beef0ee4",
|
|
685
|
+
"0xc6e00bf33da88fc2",
|
|
686
|
+
"0xd5a79147930aa725",
|
|
687
|
+
"0x06ca6351e003826f",
|
|
688
|
+
"0x142929670a0e6e70",
|
|
689
|
+
"0x27b70a8546d22ffc",
|
|
690
|
+
"0x2e1b21385c26c926",
|
|
691
|
+
"0x4d2c6dfc5ac42aed",
|
|
692
|
+
"0x53380d139d95b3df",
|
|
693
|
+
"0x650a73548baf63de",
|
|
694
|
+
"0x766a0abb3c77b2a8",
|
|
695
|
+
"0x81c2c92e47edaee6",
|
|
696
|
+
"0x92722c851482353b",
|
|
697
|
+
"0xa2bfe8a14cf10364",
|
|
698
|
+
"0xa81a664bbc423001",
|
|
699
|
+
"0xc24b8b70d0f89791",
|
|
700
|
+
"0xc76c51a30654be30",
|
|
701
|
+
"0xd192e819d6ef5218",
|
|
702
|
+
"0xd69906245565a910",
|
|
703
|
+
"0xf40e35855771202a",
|
|
704
|
+
"0x106aa07032bbd1b8",
|
|
705
|
+
"0x19a4c116b8d2d0c8",
|
|
706
|
+
"0x1e376c085141ab53",
|
|
707
|
+
"0x2748774cdf8eeb99",
|
|
708
|
+
"0x34b0bcb5e19b48a8",
|
|
709
|
+
"0x391c0cb3c5c95a63",
|
|
710
|
+
"0x4ed8aa4ae3418acb",
|
|
711
|
+
"0x5b9cca4f7763e373",
|
|
712
|
+
"0x682e6ff3d6b2b8a3",
|
|
713
|
+
"0x748f82ee5defb2fc",
|
|
714
|
+
"0x78a5636f43172f60",
|
|
715
|
+
"0x84c87814a1f0ab72",
|
|
716
|
+
"0x8cc702081a6439ec",
|
|
717
|
+
"0x90befffa23631e28",
|
|
718
|
+
"0xa4506cebde82bde9",
|
|
719
|
+
"0xbef9a3f7b2c67915",
|
|
720
|
+
"0xc67178f2e372532b",
|
|
721
|
+
"0xca273eceea26619c",
|
|
722
|
+
"0xd186b8c721c0c207",
|
|
723
|
+
"0xeada7dd6cde0eb1e",
|
|
724
|
+
"0xf57d4f7fee6ed178",
|
|
725
|
+
"0x06f067aa72176fba",
|
|
726
|
+
"0x0a637dc5a2c898a6",
|
|
727
|
+
"0x113f9804bef90dae",
|
|
728
|
+
"0x1b710b35131c471b",
|
|
729
|
+
"0x28db77f523047d84",
|
|
730
|
+
"0x32caab7b40c72493",
|
|
731
|
+
"0x3c9ebe0a15c9bebc",
|
|
732
|
+
"0x431d67c49c100d4c",
|
|
733
|
+
"0x4cc5d4becb3e42b6",
|
|
734
|
+
"0x597f299cfc657e2a",
|
|
735
|
+
"0x5fcb6fab3ad6faec",
|
|
736
|
+
"0x6c44198c4a475817"
|
|
737
|
+
].map((n) => BigInt(n))))();
|
|
738
|
+
var SHA512_Kh = /* @__PURE__ */ (() => K512[0])();
|
|
739
|
+
var SHA512_Kl = /* @__PURE__ */ (() => K512[1])();
|
|
740
|
+
var SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);
|
|
741
|
+
var SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);
|
|
742
|
+
var SHA512 = class extends HashMD {
|
|
743
|
+
constructor(outputLen = 64) {
|
|
744
|
+
super(128, outputLen, 16, false);
|
|
745
|
+
this.Ah = SHA512_IV[0] | 0;
|
|
746
|
+
this.Al = SHA512_IV[1] | 0;
|
|
747
|
+
this.Bh = SHA512_IV[2] | 0;
|
|
748
|
+
this.Bl = SHA512_IV[3] | 0;
|
|
749
|
+
this.Ch = SHA512_IV[4] | 0;
|
|
750
|
+
this.Cl = SHA512_IV[5] | 0;
|
|
751
|
+
this.Dh = SHA512_IV[6] | 0;
|
|
752
|
+
this.Dl = SHA512_IV[7] | 0;
|
|
753
|
+
this.Eh = SHA512_IV[8] | 0;
|
|
754
|
+
this.El = SHA512_IV[9] | 0;
|
|
755
|
+
this.Fh = SHA512_IV[10] | 0;
|
|
756
|
+
this.Fl = SHA512_IV[11] | 0;
|
|
757
|
+
this.Gh = SHA512_IV[12] | 0;
|
|
758
|
+
this.Gl = SHA512_IV[13] | 0;
|
|
759
|
+
this.Hh = SHA512_IV[14] | 0;
|
|
760
|
+
this.Hl = SHA512_IV[15] | 0;
|
|
761
|
+
}
|
|
762
|
+
// prettier-ignore
|
|
763
|
+
get() {
|
|
764
|
+
const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
|
|
765
|
+
return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];
|
|
766
|
+
}
|
|
767
|
+
// prettier-ignore
|
|
768
|
+
set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {
|
|
769
|
+
this.Ah = Ah | 0;
|
|
770
|
+
this.Al = Al | 0;
|
|
771
|
+
this.Bh = Bh | 0;
|
|
772
|
+
this.Bl = Bl | 0;
|
|
773
|
+
this.Ch = Ch | 0;
|
|
774
|
+
this.Cl = Cl | 0;
|
|
775
|
+
this.Dh = Dh | 0;
|
|
776
|
+
this.Dl = Dl | 0;
|
|
777
|
+
this.Eh = Eh | 0;
|
|
778
|
+
this.El = El | 0;
|
|
779
|
+
this.Fh = Fh | 0;
|
|
780
|
+
this.Fl = Fl | 0;
|
|
781
|
+
this.Gh = Gh | 0;
|
|
782
|
+
this.Gl = Gl | 0;
|
|
783
|
+
this.Hh = Hh | 0;
|
|
784
|
+
this.Hl = Hl | 0;
|
|
785
|
+
}
|
|
786
|
+
process(view, offset) {
|
|
787
|
+
for (let i = 0; i < 16; i++, offset += 4) {
|
|
788
|
+
SHA512_W_H[i] = view.getUint32(offset);
|
|
789
|
+
SHA512_W_L[i] = view.getUint32(offset += 4);
|
|
790
|
+
}
|
|
791
|
+
for (let i = 16; i < 80; i++) {
|
|
792
|
+
const W15h = SHA512_W_H[i - 15] | 0;
|
|
793
|
+
const W15l = SHA512_W_L[i - 15] | 0;
|
|
794
|
+
const s0h = rotrSH(W15h, W15l, 1) ^ rotrSH(W15h, W15l, 8) ^ shrSH(W15h, W15l, 7);
|
|
795
|
+
const s0l = rotrSL(W15h, W15l, 1) ^ rotrSL(W15h, W15l, 8) ^ shrSL(W15h, W15l, 7);
|
|
796
|
+
const W2h = SHA512_W_H[i - 2] | 0;
|
|
797
|
+
const W2l = SHA512_W_L[i - 2] | 0;
|
|
798
|
+
const s1h = rotrSH(W2h, W2l, 19) ^ rotrBH(W2h, W2l, 61) ^ shrSH(W2h, W2l, 6);
|
|
799
|
+
const s1l = rotrSL(W2h, W2l, 19) ^ rotrBL(W2h, W2l, 61) ^ shrSL(W2h, W2l, 6);
|
|
800
|
+
const SUMl = add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);
|
|
801
|
+
const SUMh = add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);
|
|
802
|
+
SHA512_W_H[i] = SUMh | 0;
|
|
803
|
+
SHA512_W_L[i] = SUMl | 0;
|
|
804
|
+
}
|
|
805
|
+
let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
|
|
806
|
+
for (let i = 0; i < 80; i++) {
|
|
807
|
+
const sigma1h = rotrSH(Eh, El, 14) ^ rotrSH(Eh, El, 18) ^ rotrBH(Eh, El, 41);
|
|
808
|
+
const sigma1l = rotrSL(Eh, El, 14) ^ rotrSL(Eh, El, 18) ^ rotrBL(Eh, El, 41);
|
|
809
|
+
const CHIh = Eh & Fh ^ ~Eh & Gh;
|
|
810
|
+
const CHIl = El & Fl ^ ~El & Gl;
|
|
811
|
+
const T1ll = add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);
|
|
812
|
+
const T1h = add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);
|
|
813
|
+
const T1l = T1ll | 0;
|
|
814
|
+
const sigma0h = rotrSH(Ah, Al, 28) ^ rotrBH(Ah, Al, 34) ^ rotrBH(Ah, Al, 39);
|
|
815
|
+
const sigma0l = rotrSL(Ah, Al, 28) ^ rotrBL(Ah, Al, 34) ^ rotrBL(Ah, Al, 39);
|
|
816
|
+
const MAJh = Ah & Bh ^ Ah & Ch ^ Bh & Ch;
|
|
817
|
+
const MAJl = Al & Bl ^ Al & Cl ^ Bl & Cl;
|
|
818
|
+
Hh = Gh | 0;
|
|
819
|
+
Hl = Gl | 0;
|
|
820
|
+
Gh = Fh | 0;
|
|
821
|
+
Gl = Fl | 0;
|
|
822
|
+
Fh = Eh | 0;
|
|
823
|
+
Fl = El | 0;
|
|
824
|
+
({ h: Eh, l: El } = add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));
|
|
825
|
+
Dh = Ch | 0;
|
|
826
|
+
Dl = Cl | 0;
|
|
827
|
+
Ch = Bh | 0;
|
|
828
|
+
Cl = Bl | 0;
|
|
829
|
+
Bh = Ah | 0;
|
|
830
|
+
Bl = Al | 0;
|
|
831
|
+
const All = add3L(T1l, sigma0l, MAJl);
|
|
832
|
+
Ah = add3H(All, T1h, sigma0h, MAJh);
|
|
833
|
+
Al = All | 0;
|
|
48
834
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
835
|
+
({ h: Ah, l: Al } = add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));
|
|
836
|
+
({ h: Bh, l: Bl } = add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));
|
|
837
|
+
({ h: Ch, l: Cl } = add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));
|
|
838
|
+
({ h: Dh, l: Dl } = add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));
|
|
839
|
+
({ h: Eh, l: El } = add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));
|
|
840
|
+
({ h: Fh, l: Fl } = add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));
|
|
841
|
+
({ h: Gh, l: Gl } = add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));
|
|
842
|
+
({ h: Hh, l: Hl } = add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));
|
|
843
|
+
this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);
|
|
844
|
+
}
|
|
845
|
+
roundClean() {
|
|
846
|
+
clean(SHA512_W_H, SHA512_W_L);
|
|
847
|
+
}
|
|
848
|
+
destroy() {
|
|
849
|
+
clean(this.buffer);
|
|
850
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
var sha512 = /* @__PURE__ */ createHasher(() => new SHA512());
|
|
854
|
+
|
|
855
|
+
// ../../node_modules/.pnpm/@noble+hashes@1.8.0/node_modules/@noble/hashes/esm/sha512.js
|
|
856
|
+
var sha5122 = sha512;
|
|
857
|
+
|
|
858
|
+
// src/index.ts
|
|
859
|
+
if (!hashes.sha512) {
|
|
860
|
+
hashes.sha512 = (msg) => sha5122(msg);
|
|
861
|
+
}
|
|
862
|
+
function parseYamlValue(raw) {
|
|
863
|
+
const trimmed = raw.trim();
|
|
864
|
+
if (trimmed === "null") return null;
|
|
865
|
+
if (trimmed === "true") return true;
|
|
866
|
+
if (trimmed === "false") return false;
|
|
867
|
+
if (trimmed === "[]") return [];
|
|
868
|
+
if (trimmed === "{}") return {};
|
|
869
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
870
|
+
return JSON.parse(trimmed);
|
|
871
|
+
}
|
|
872
|
+
const num = Number(trimmed);
|
|
873
|
+
if (trimmed !== "" && !isNaN(num) && isFinite(num)) return num;
|
|
874
|
+
return trimmed;
|
|
53
875
|
}
|
|
54
876
|
function parseYaml(text) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
obj[nk] = parseYamlValue(nv);
|
|
88
|
-
i = j;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (currentArray)
|
|
96
|
-
currentArray.push(obj);
|
|
877
|
+
const lines = text.split("\n");
|
|
878
|
+
const root = {};
|
|
879
|
+
const stack = [
|
|
880
|
+
{ obj: root, indent: -1 }
|
|
881
|
+
];
|
|
882
|
+
let currentArray = null;
|
|
883
|
+
let currentArrayIndent = -1;
|
|
884
|
+
for (let i = 0; i < lines.length; i++) {
|
|
885
|
+
const line = lines[i];
|
|
886
|
+
if (line.trim() === "" || line.trim().startsWith("#")) continue;
|
|
887
|
+
const lineIndent = line.length - line.trimStart().length;
|
|
888
|
+
const trimmed = line.trimStart();
|
|
889
|
+
if (trimmed.startsWith("- ")) {
|
|
890
|
+
const itemContent = trimmed.slice(2);
|
|
891
|
+
const colonIdx2 = itemContent.indexOf(": ");
|
|
892
|
+
if (colonIdx2 !== -1) {
|
|
893
|
+
const obj = {};
|
|
894
|
+
const key = itemContent.slice(0, colonIdx2);
|
|
895
|
+
const val = itemContent.slice(colonIdx2 + 2);
|
|
896
|
+
obj[key] = parseYamlValue(val);
|
|
897
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
898
|
+
const nextLine = lines[j];
|
|
899
|
+
if (nextLine.trim() === "") continue;
|
|
900
|
+
const nextIndent = nextLine.length - nextLine.trimStart().length;
|
|
901
|
+
const nextTrimmed = nextLine.trimStart();
|
|
902
|
+
if (nextIndent > lineIndent && !nextTrimmed.startsWith("- ")) {
|
|
903
|
+
const nextColonIdx = nextTrimmed.indexOf(": ");
|
|
904
|
+
if (nextColonIdx !== -1) {
|
|
905
|
+
const nk = nextTrimmed.slice(0, nextColonIdx);
|
|
906
|
+
const nv = nextTrimmed.slice(nextColonIdx + 2);
|
|
907
|
+
obj[nk] = parseYamlValue(nv);
|
|
908
|
+
i = j;
|
|
97
909
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
const colonIdx = trimmed.indexOf(": ");
|
|
105
|
-
const endsWithColon = trimmed.endsWith(":") && colonIdx === -1;
|
|
106
|
-
if (endsWithColon) {
|
|
107
|
-
const key = trimmed.slice(0, -1);
|
|
108
|
-
if (currentArray && lineIndent <= currentArrayIndent) {
|
|
109
|
-
currentArray = null;
|
|
110
|
-
currentArrayIndent = -1;
|
|
111
|
-
}
|
|
112
|
-
while (stack.length > 1 && stack[stack.length - 1].indent >= lineIndent) {
|
|
113
|
-
stack.pop();
|
|
114
|
-
}
|
|
115
|
-
const parent = stack[stack.length - 1].obj;
|
|
116
|
-
let nextIdx = i + 1;
|
|
117
|
-
while (nextIdx < lines.length && lines[nextIdx].trim() === "")
|
|
118
|
-
nextIdx++;
|
|
119
|
-
if (nextIdx < lines.length && lines[nextIdx].trimStart().startsWith("- ")) {
|
|
120
|
-
const arr = [];
|
|
121
|
-
parent[key] = arr;
|
|
122
|
-
currentArray = arr;
|
|
123
|
-
currentArrayIndent = lineIndent;
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
const nested = {};
|
|
127
|
-
parent[key] = nested;
|
|
128
|
-
stack.push({ obj: nested, indent: lineIndent });
|
|
129
|
-
}
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (colonIdx !== -1) {
|
|
133
|
-
if (currentArray && lineIndent <= currentArrayIndent) {
|
|
134
|
-
currentArray = null;
|
|
135
|
-
currentArrayIndent = -1;
|
|
136
|
-
}
|
|
137
|
-
while (stack.length > 1 && stack[stack.length - 1].indent >= lineIndent) {
|
|
138
|
-
stack.pop();
|
|
139
|
-
}
|
|
140
|
-
const key = trimmed.slice(0, colonIdx);
|
|
141
|
-
const val = trimmed.slice(colonIdx + 2);
|
|
142
|
-
const parent = stack[stack.length - 1].obj;
|
|
143
|
-
parent[key] = parseYamlValue(val);
|
|
910
|
+
} else {
|
|
911
|
+
break;
|
|
912
|
+
}
|
|
144
913
|
}
|
|
914
|
+
if (currentArray) currentArray.push(obj);
|
|
915
|
+
} else {
|
|
916
|
+
if (currentArray) currentArray.push(parseYamlValue(itemContent));
|
|
917
|
+
}
|
|
918
|
+
continue;
|
|
919
|
+
}
|
|
920
|
+
const colonIdx = trimmed.indexOf(": ");
|
|
921
|
+
const endsWithColon = trimmed.endsWith(":") && colonIdx === -1;
|
|
922
|
+
if (endsWithColon) {
|
|
923
|
+
const key = trimmed.slice(0, -1);
|
|
924
|
+
if (currentArray && lineIndent <= currentArrayIndent) {
|
|
925
|
+
currentArray = null;
|
|
926
|
+
currentArrayIndent = -1;
|
|
927
|
+
}
|
|
928
|
+
while (stack.length > 1 && stack[stack.length - 1].indent >= lineIndent) {
|
|
929
|
+
stack.pop();
|
|
930
|
+
}
|
|
931
|
+
const parent = stack[stack.length - 1].obj;
|
|
932
|
+
let nextIdx = i + 1;
|
|
933
|
+
while (nextIdx < lines.length && lines[nextIdx].trim() === "") nextIdx++;
|
|
934
|
+
if (nextIdx < lines.length && lines[nextIdx].trimStart().startsWith("- ")) {
|
|
935
|
+
const arr = [];
|
|
936
|
+
parent[key] = arr;
|
|
937
|
+
currentArray = arr;
|
|
938
|
+
currentArrayIndent = lineIndent;
|
|
939
|
+
} else {
|
|
940
|
+
const nested = {};
|
|
941
|
+
parent[key] = nested;
|
|
942
|
+
stack.push({ obj: nested, indent: lineIndent });
|
|
943
|
+
}
|
|
944
|
+
continue;
|
|
145
945
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
946
|
+
if (colonIdx !== -1) {
|
|
947
|
+
if (currentArray && lineIndent <= currentArrayIndent) {
|
|
948
|
+
currentArray = null;
|
|
949
|
+
currentArrayIndent = -1;
|
|
950
|
+
}
|
|
951
|
+
while (stack.length > 1 && stack[stack.length - 1].indent >= lineIndent) {
|
|
952
|
+
stack.pop();
|
|
953
|
+
}
|
|
954
|
+
const key = trimmed.slice(0, colonIdx);
|
|
955
|
+
const val = trimmed.slice(colonIdx + 2);
|
|
956
|
+
const parent = stack[stack.length - 1].obj;
|
|
957
|
+
parent[key] = parseYamlValue(val);
|
|
155
958
|
}
|
|
156
|
-
|
|
959
|
+
}
|
|
960
|
+
return root;
|
|
961
|
+
}
|
|
962
|
+
function hexToBytes2(hex) {
|
|
963
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
964
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
965
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
966
|
+
}
|
|
967
|
+
return bytes;
|
|
157
968
|
}
|
|
158
969
|
function fromBase64Url(str) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
bytes[i] = binary.charCodeAt(i);
|
|
170
|
-
}
|
|
171
|
-
return bytes;
|
|
970
|
+
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
971
|
+
const pad = base64.length % 4;
|
|
972
|
+
if (pad === 2) base64 += "==";
|
|
973
|
+
else if (pad === 3) base64 += "=";
|
|
974
|
+
const binary = atob(base64);
|
|
975
|
+
const bytes = new Uint8Array(binary.length);
|
|
976
|
+
for (let i = 0; i < binary.length; i++) {
|
|
977
|
+
bytes[i] = binary.charCodeAt(i);
|
|
978
|
+
}
|
|
979
|
+
return bytes;
|
|
172
980
|
}
|
|
173
|
-
// ===========================================================================
|
|
174
|
-
// Canonical JSON (JCS/RFC 8785) — must match @motebit/crypto exactly
|
|
175
|
-
// ===========================================================================
|
|
176
981
|
function canonicalJson(obj) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
entries.push(JSON.stringify(key) + ":" + canonicalJson(val));
|
|
191
|
-
}
|
|
192
|
-
return "{" + entries.join(",") + "}";
|
|
982
|
+
if (obj === null || obj === void 0) return JSON.stringify(obj);
|
|
983
|
+
if (typeof obj !== "object") return JSON.stringify(obj);
|
|
984
|
+
if (Array.isArray(obj)) {
|
|
985
|
+
return "[" + obj.map((item) => canonicalJson(item)).join(",") + "]";
|
|
986
|
+
}
|
|
987
|
+
const sorted = Object.keys(obj).sort();
|
|
988
|
+
const entries = [];
|
|
989
|
+
for (const key of sorted) {
|
|
990
|
+
const val = obj[key];
|
|
991
|
+
if (val === void 0) continue;
|
|
992
|
+
entries.push(JSON.stringify(key) + ":" + canonicalJson(val));
|
|
993
|
+
}
|
|
994
|
+
return "{" + entries.join(",") + "}";
|
|
193
995
|
}
|
|
194
|
-
|
|
195
|
-
// Base58btc encoding/decoding (for did:key and VC proof values)
|
|
196
|
-
// ===========================================================================
|
|
197
|
-
const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
996
|
+
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
198
997
|
function base58btcEncode(bytes) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return BASE58_ALPHABET[0].repeat(zeros) + result;
|
|
998
|
+
let zeros = 0;
|
|
999
|
+
while (zeros < bytes.length && bytes[zeros] === 0) zeros++;
|
|
1000
|
+
let value = 0n;
|
|
1001
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1002
|
+
value = value * 256n + BigInt(bytes[i]);
|
|
1003
|
+
}
|
|
1004
|
+
let result = "";
|
|
1005
|
+
while (value > 0n) {
|
|
1006
|
+
const remainder = Number(value % 58n);
|
|
1007
|
+
value = value / 58n;
|
|
1008
|
+
result = BASE58_ALPHABET[remainder] + result;
|
|
1009
|
+
}
|
|
1010
|
+
return BASE58_ALPHABET[0].repeat(zeros) + result;
|
|
213
1011
|
}
|
|
214
1012
|
function base58btcDecode(str) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
return result;
|
|
235
|
-
}
|
|
236
|
-
// ===========================================================================
|
|
237
|
-
// did:key derivation and parsing
|
|
238
|
-
// ===========================================================================
|
|
1013
|
+
let zeros = 0;
|
|
1014
|
+
while (zeros < str.length && str[zeros] === BASE58_ALPHABET[0]) zeros++;
|
|
1015
|
+
let value = 0n;
|
|
1016
|
+
for (let i = 0; i < str.length; i++) {
|
|
1017
|
+
const idx = BASE58_ALPHABET.indexOf(str[i]);
|
|
1018
|
+
if (idx === -1) throw new Error(`Invalid base58 character: ${str[i]}`);
|
|
1019
|
+
value = value * 58n + BigInt(idx);
|
|
1020
|
+
}
|
|
1021
|
+
const hex = [];
|
|
1022
|
+
while (value > 0n) {
|
|
1023
|
+
const byte = Number(value & 0xffn);
|
|
1024
|
+
hex.unshift(byte.toString(16).padStart(2, "0"));
|
|
1025
|
+
value >>= 8n;
|
|
1026
|
+
}
|
|
1027
|
+
const dataBytes = hex.length > 0 ? new Uint8Array(hex.map((h2) => parseInt(h2, 16))) : new Uint8Array(0);
|
|
1028
|
+
const result = new Uint8Array(zeros + dataBytes.length);
|
|
1029
|
+
result.set(dataBytes, zeros);
|
|
1030
|
+
return result;
|
|
1031
|
+
}
|
|
239
1032
|
function publicKeyToDidKey(pubKey) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
1033
|
+
const prefixed = new Uint8Array(34);
|
|
1034
|
+
prefixed[0] = 237;
|
|
1035
|
+
prefixed[1] = 1;
|
|
1036
|
+
prefixed.set(pubKey, 2);
|
|
1037
|
+
return `did:key:z${base58btcEncode(prefixed)}`;
|
|
245
1038
|
}
|
|
246
1039
|
function didKeyToPublicKey(did) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
1040
|
+
if (!did.startsWith("did:key:z")) {
|
|
1041
|
+
throw new Error("Invalid did:key URI: must start with did:key:z");
|
|
1042
|
+
}
|
|
1043
|
+
const encoded = did.slice("did:key:z".length);
|
|
1044
|
+
const decoded = base58btcDecode(encoded);
|
|
1045
|
+
if (decoded.length !== 34) {
|
|
1046
|
+
throw new Error(
|
|
1047
|
+
`Invalid did:key: expected 34 bytes (2 prefix + 32 key), got ${decoded.length}`
|
|
1048
|
+
);
|
|
1049
|
+
}
|
|
1050
|
+
if (decoded[0] !== 237 || decoded[1] !== 1) {
|
|
1051
|
+
throw new Error("Invalid did:key: multicodec prefix is not ed25519-pub (0xed01)");
|
|
1052
|
+
}
|
|
1053
|
+
return decoded.slice(2);
|
|
259
1054
|
}
|
|
260
|
-
// ===========================================================================
|
|
261
|
-
// SHA-256 (Web Crypto — available in Node 18+ and all browsers)
|
|
262
|
-
// ===========================================================================
|
|
263
1055
|
async function sha256(data) {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
// ===========================================================================
|
|
270
|
-
const SIG_PREFIX = "<!-- motebit:sig:Ed25519:";
|
|
271
|
-
const SIG_SUFFIX = " -->";
|
|
272
|
-
// ===========================================================================
|
|
273
|
-
// Artifact detection
|
|
274
|
-
// ===========================================================================
|
|
1056
|
+
const buf = await crypto.subtle.digest("SHA-256", data);
|
|
1057
|
+
return new Uint8Array(buf);
|
|
1058
|
+
}
|
|
1059
|
+
var SIG_PREFIX = "<!-- motebit:sig:Ed25519:";
|
|
1060
|
+
var SIG_SUFFIX = " -->";
|
|
275
1061
|
function detectArtifactType(artifact) {
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
|
|
279
|
-
if (artifact.includes("---")) {
|
|
280
|
-
return "identity";
|
|
281
|
-
}
|
|
282
|
-
// Try parsing as JSON
|
|
283
|
-
try {
|
|
284
|
-
const parsed = JSON.parse(artifact);
|
|
285
|
-
return detectArtifactType(parsed);
|
|
286
|
-
}
|
|
287
|
-
catch {
|
|
288
|
-
return null;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
if (typeof artifact !== "object" || artifact === null)
|
|
292
|
-
return null;
|
|
293
|
-
const obj = artifact;
|
|
294
|
-
// Verifiable Presentation: has "holder" + "verifiableCredential" + "proof"
|
|
295
|
-
if ("holder" in obj && "verifiableCredential" in obj && "proof" in obj) {
|
|
296
|
-
return "presentation";
|
|
1062
|
+
if (typeof artifact === "string") {
|
|
1063
|
+
if (artifact.includes("---")) {
|
|
1064
|
+
return "identity";
|
|
297
1065
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if ("task_id" in obj && "motebit_id" in obj && "signature" in obj && "prompt_hash" in obj) {
|
|
304
|
-
return "receipt";
|
|
1066
|
+
try {
|
|
1067
|
+
const parsed = JSON.parse(artifact);
|
|
1068
|
+
return detectArtifactType(parsed);
|
|
1069
|
+
} catch {
|
|
1070
|
+
return null;
|
|
305
1071
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
1072
|
+
}
|
|
1073
|
+
if (typeof artifact !== "object" || artifact === null) return null;
|
|
1074
|
+
const obj = artifact;
|
|
1075
|
+
if ("holder" in obj && "verifiableCredential" in obj && "proof" in obj) {
|
|
1076
|
+
return "presentation";
|
|
1077
|
+
}
|
|
1078
|
+
if ("credentialSubject" in obj && "issuer" in obj && "proof" in obj) {
|
|
1079
|
+
return "credential";
|
|
1080
|
+
}
|
|
1081
|
+
if ("task_id" in obj && "motebit_id" in obj && "signature" in obj && "prompt_hash" in obj) {
|
|
1082
|
+
return "receipt";
|
|
1083
|
+
}
|
|
1084
|
+
return null;
|
|
1085
|
+
}
|
|
1086
|
+
function parse(content) {
|
|
1087
|
+
const firstDash = content.indexOf("---\n");
|
|
1088
|
+
if (firstDash === -1) throw new Error("Missing frontmatter opening ---");
|
|
1089
|
+
const bodyStart = firstDash + 4;
|
|
1090
|
+
const secondDash = content.indexOf("\n---", bodyStart);
|
|
1091
|
+
if (secondDash === -1) throw new Error("Missing frontmatter closing ---");
|
|
1092
|
+
const rawFrontmatter = content.slice(bodyStart, secondDash);
|
|
1093
|
+
const frontmatter = parseYaml(rawFrontmatter);
|
|
1094
|
+
const sigStart = content.indexOf(SIG_PREFIX);
|
|
1095
|
+
if (sigStart === -1) throw new Error("Missing signature");
|
|
1096
|
+
const sigValueStart = sigStart + SIG_PREFIX.length;
|
|
1097
|
+
const sigEnd = content.indexOf(SIG_SUFFIX, sigValueStart);
|
|
1098
|
+
if (sigEnd === -1) throw new Error("Malformed signature");
|
|
1099
|
+
const signature = content.slice(sigValueStart, sigEnd);
|
|
1100
|
+
return { frontmatter, signature, rawFrontmatter };
|
|
334
1101
|
}
|
|
335
1102
|
function identityError(msg) {
|
|
336
|
-
|
|
1103
|
+
return { type: "identity", valid: false, identity: null, error: msg, errors: [{ message: msg }] };
|
|
337
1104
|
}
|
|
338
1105
|
async function verifyIdentity(content) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
identity: parsed.frontmatter,
|
|
391
|
-
did: publicKeyToDidKey(pubKey),
|
|
392
|
-
...(successionResult ? { succession: successionResult } : {}),
|
|
393
|
-
};
|
|
1106
|
+
let parsed;
|
|
1107
|
+
try {
|
|
1108
|
+
parsed = parse(content);
|
|
1109
|
+
} catch (err2) {
|
|
1110
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
1111
|
+
return identityError(msg);
|
|
1112
|
+
}
|
|
1113
|
+
const pubKeyHex = parsed.frontmatter.identity?.public_key;
|
|
1114
|
+
if (!pubKeyHex) {
|
|
1115
|
+
return identityError("No public key in frontmatter");
|
|
1116
|
+
}
|
|
1117
|
+
let pubKey;
|
|
1118
|
+
try {
|
|
1119
|
+
pubKey = hexToBytes2(pubKeyHex);
|
|
1120
|
+
} catch {
|
|
1121
|
+
return identityError("Invalid public key hex");
|
|
1122
|
+
}
|
|
1123
|
+
if (pubKey.length !== 32) {
|
|
1124
|
+
return identityError("Public key must be 32 bytes");
|
|
1125
|
+
}
|
|
1126
|
+
let sigBytes;
|
|
1127
|
+
try {
|
|
1128
|
+
sigBytes = fromBase64Url(parsed.signature);
|
|
1129
|
+
} catch {
|
|
1130
|
+
return identityError("Invalid signature encoding");
|
|
1131
|
+
}
|
|
1132
|
+
if (sigBytes.length !== 64) {
|
|
1133
|
+
return identityError("Signature must be 64 bytes");
|
|
1134
|
+
}
|
|
1135
|
+
const frontmatterBytes = new TextEncoder().encode(parsed.rawFrontmatter);
|
|
1136
|
+
let valid;
|
|
1137
|
+
try {
|
|
1138
|
+
valid = await verifyAsync(sigBytes, frontmatterBytes, pubKey);
|
|
1139
|
+
} catch {
|
|
1140
|
+
valid = false;
|
|
1141
|
+
}
|
|
1142
|
+
if (!valid) {
|
|
1143
|
+
return identityError("Signature verification failed");
|
|
1144
|
+
}
|
|
1145
|
+
const chain = parsed.frontmatter.succession;
|
|
1146
|
+
let successionResult;
|
|
1147
|
+
if (chain && chain.length > 0) {
|
|
1148
|
+
successionResult = await verifySuccessionChain(chain, pubKeyHex);
|
|
1149
|
+
}
|
|
1150
|
+
return {
|
|
1151
|
+
type: "identity",
|
|
1152
|
+
valid: true,
|
|
1153
|
+
identity: parsed.frontmatter,
|
|
1154
|
+
did: publicKeyToDidKey(pubKey),
|
|
1155
|
+
...successionResult ? { succession: successionResult } : {}
|
|
1156
|
+
};
|
|
394
1157
|
}
|
|
395
|
-
// ===========================================================================
|
|
396
|
-
// Succession chain verification
|
|
397
|
-
// ===========================================================================
|
|
398
1158
|
async function verifySuccessionChain(chain, currentPublicKeyHex) {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
return {
|
|
417
|
-
valid: false,
|
|
418
|
-
rotations: chain.length,
|
|
419
|
-
error: `Succession record ${i}: old_key_signature verification failed`,
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
const newPubKey = hexToBytes(record.new_public_key);
|
|
423
|
-
const newSig = hexToBytes(record.new_key_signature);
|
|
424
|
-
const newValid = await ed.verifyAsync(newSig, message, newPubKey);
|
|
425
|
-
if (!newValid) {
|
|
426
|
-
return {
|
|
427
|
-
valid: false,
|
|
428
|
-
rotations: chain.length,
|
|
429
|
-
error: `Succession record ${i}: new_key_signature verification failed`,
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
if (i < chain.length - 1) {
|
|
433
|
-
const next = chain[i + 1];
|
|
434
|
-
if (record.new_public_key !== next.old_public_key) {
|
|
435
|
-
return {
|
|
436
|
-
valid: false,
|
|
437
|
-
rotations: chain.length,
|
|
438
|
-
error: `Succession chain broken at record ${i}: new_public_key does not match next record's old_public_key`,
|
|
439
|
-
};
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
if (i < chain.length - 1) {
|
|
443
|
-
const next = chain[i + 1];
|
|
444
|
-
if (record.timestamp >= next.timestamp) {
|
|
445
|
-
return {
|
|
446
|
-
valid: false,
|
|
447
|
-
rotations: chain.length,
|
|
448
|
-
error: `Succession chain temporal ordering violated at record ${i}`,
|
|
449
|
-
};
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
const lastRecord = chain[chain.length - 1];
|
|
454
|
-
if (lastRecord.new_public_key !== currentPublicKeyHex) {
|
|
455
|
-
return {
|
|
456
|
-
valid: false,
|
|
457
|
-
rotations: chain.length,
|
|
458
|
-
error: "Succession chain terminal: last new_public_key does not match identity public_key",
|
|
459
|
-
};
|
|
460
|
-
}
|
|
1159
|
+
try {
|
|
1160
|
+
for (let i = 0; i < chain.length; i++) {
|
|
1161
|
+
const record = chain[i];
|
|
1162
|
+
const payloadObj = {
|
|
1163
|
+
old_public_key: record.old_public_key,
|
|
1164
|
+
new_public_key: record.new_public_key,
|
|
1165
|
+
timestamp: record.timestamp
|
|
1166
|
+
};
|
|
1167
|
+
if (record.reason !== void 0) {
|
|
1168
|
+
payloadObj.reason = record.reason;
|
|
1169
|
+
}
|
|
1170
|
+
const payload = canonicalJson(payloadObj);
|
|
1171
|
+
const message = new TextEncoder().encode(payload);
|
|
1172
|
+
const oldPubKey = hexToBytes2(record.old_public_key);
|
|
1173
|
+
const oldSig = hexToBytes2(record.old_key_signature);
|
|
1174
|
+
const oldValid = await verifyAsync(oldSig, message, oldPubKey);
|
|
1175
|
+
if (!oldValid) {
|
|
461
1176
|
return {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
1177
|
+
valid: false,
|
|
1178
|
+
rotations: chain.length,
|
|
1179
|
+
error: `Succession record ${i}: old_key_signature verification failed`
|
|
465
1180
|
};
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
1181
|
+
}
|
|
1182
|
+
const newPubKey = hexToBytes2(record.new_public_key);
|
|
1183
|
+
const newSig = hexToBytes2(record.new_key_signature);
|
|
1184
|
+
const newValid = await verifyAsync(newSig, message, newPubKey);
|
|
1185
|
+
if (!newValid) {
|
|
469
1186
|
return {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
1187
|
+
valid: false,
|
|
1188
|
+
rotations: chain.length,
|
|
1189
|
+
error: `Succession record ${i}: new_key_signature verification failed`
|
|
473
1190
|
};
|
|
1191
|
+
}
|
|
1192
|
+
if (i < chain.length - 1) {
|
|
1193
|
+
const next = chain[i + 1];
|
|
1194
|
+
if (record.new_public_key !== next.old_public_key) {
|
|
1195
|
+
return {
|
|
1196
|
+
valid: false,
|
|
1197
|
+
rotations: chain.length,
|
|
1198
|
+
error: `Succession chain broken at record ${i}: new_public_key does not match next record's old_public_key`
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
if (i < chain.length - 1) {
|
|
1203
|
+
const next = chain[i + 1];
|
|
1204
|
+
if (record.timestamp >= next.timestamp) {
|
|
1205
|
+
return {
|
|
1206
|
+
valid: false,
|
|
1207
|
+
rotations: chain.length,
|
|
1208
|
+
error: `Succession chain temporal ordering violated at record ${i}`
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
474
1212
|
}
|
|
1213
|
+
const lastRecord = chain[chain.length - 1];
|
|
1214
|
+
if (lastRecord.new_public_key !== currentPublicKeyHex) {
|
|
1215
|
+
return {
|
|
1216
|
+
valid: false,
|
|
1217
|
+
rotations: chain.length,
|
|
1218
|
+
error: "Succession chain terminal: last new_public_key does not match identity public_key"
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
return {
|
|
1222
|
+
valid: true,
|
|
1223
|
+
genesis_public_key: chain[0].old_public_key,
|
|
1224
|
+
rotations: chain.length
|
|
1225
|
+
};
|
|
1226
|
+
} catch (err2) {
|
|
1227
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
1228
|
+
return {
|
|
1229
|
+
valid: false,
|
|
1230
|
+
rotations: 0,
|
|
1231
|
+
error: `Succession verification error: ${msg}`
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
475
1234
|
}
|
|
476
|
-
// ===========================================================================
|
|
477
|
-
// Receipt verification
|
|
478
|
-
// ===========================================================================
|
|
479
1235
|
async function verifyReceiptSignature(receipt, publicKey) {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
return { valid: false, error: "Ed25519 verification threw" };
|
|
502
|
-
}
|
|
1236
|
+
const { signature, ...body } = receipt;
|
|
1237
|
+
if (!signature || signature.trim() === "") {
|
|
1238
|
+
return { valid: false, error: "Receipt signature is empty" };
|
|
1239
|
+
}
|
|
1240
|
+
let sig;
|
|
1241
|
+
try {
|
|
1242
|
+
sig = fromBase64Url(signature);
|
|
1243
|
+
} catch {
|
|
1244
|
+
return { valid: false, error: "Receipt signature is not valid base64url" };
|
|
1245
|
+
}
|
|
1246
|
+
if (sig.length !== 64) {
|
|
1247
|
+
return { valid: false, error: `Receipt signature must be 64 bytes, got ${sig.length}` };
|
|
1248
|
+
}
|
|
1249
|
+
const canonical = canonicalJson(body);
|
|
1250
|
+
const message = new TextEncoder().encode(canonical);
|
|
1251
|
+
try {
|
|
1252
|
+
const valid = await verifyAsync(sig, message, publicKey);
|
|
1253
|
+
return { valid };
|
|
1254
|
+
} catch {
|
|
1255
|
+
return { valid: false, error: "Ed25519 verification threw" };
|
|
1256
|
+
}
|
|
503
1257
|
}
|
|
504
1258
|
async function verifyReceipt(receipt) {
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
catch {
|
|
519
|
-
publicKey = null;
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
if (!publicKey) {
|
|
523
|
-
// Recursively verify delegations even if root can't be verified
|
|
524
|
-
const delegations = await verifyReceiptDelegations(receipt);
|
|
525
|
-
return {
|
|
526
|
-
type: "receipt",
|
|
527
|
-
valid: false,
|
|
528
|
-
receipt,
|
|
529
|
-
errors: [{ message: "No embedded public_key — cannot verify without known keys" }],
|
|
530
|
-
...(delegations.length > 0 ? { delegations } : {}),
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
const sigResult = await verifyReceiptSignature(receipt, publicKey);
|
|
534
|
-
const errors = [];
|
|
535
|
-
if (!sigResult.valid) {
|
|
536
|
-
errors.push({ message: sigResult.error ?? "Receipt signature verification failed" });
|
|
537
|
-
}
|
|
538
|
-
// Recursively verify delegation receipts
|
|
539
|
-
const delegations = await verifyReceiptDelegations(receipt);
|
|
540
|
-
const delegationErrors = delegations.filter((d) => !d.valid);
|
|
541
|
-
for (const d of delegationErrors) {
|
|
542
|
-
errors.push({
|
|
543
|
-
message: `Delegation ${d.receipt?.task_id ?? "unknown"}: verification failed`,
|
|
544
|
-
path: `delegation_receipts`,
|
|
545
|
-
});
|
|
1259
|
+
let publicKey = null;
|
|
1260
|
+
let signerDid;
|
|
1261
|
+
if (receipt.public_key) {
|
|
1262
|
+
try {
|
|
1263
|
+
publicKey = hexToBytes2(receipt.public_key);
|
|
1264
|
+
if (publicKey.length === 32) {
|
|
1265
|
+
signerDid = publicKeyToDidKey(publicKey);
|
|
1266
|
+
} else {
|
|
1267
|
+
publicKey = null;
|
|
1268
|
+
}
|
|
1269
|
+
} catch {
|
|
1270
|
+
publicKey = null;
|
|
546
1271
|
}
|
|
1272
|
+
}
|
|
1273
|
+
if (!publicKey) {
|
|
1274
|
+
const delegations2 = await verifyReceiptDelegations(receipt);
|
|
547
1275
|
return {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
...(errors.length > 0 ? { errors } : {}),
|
|
1276
|
+
type: "receipt",
|
|
1277
|
+
valid: false,
|
|
1278
|
+
receipt,
|
|
1279
|
+
errors: [{ message: "No embedded public_key \u2014 cannot verify without known keys" }],
|
|
1280
|
+
...delegations2.length > 0 ? { delegations: delegations2 } : {}
|
|
554
1281
|
};
|
|
1282
|
+
}
|
|
1283
|
+
const sigResult = await verifyReceiptSignature(receipt, publicKey);
|
|
1284
|
+
const errors = [];
|
|
1285
|
+
if (!sigResult.valid) {
|
|
1286
|
+
errors.push({ message: sigResult.error ?? "Receipt signature verification failed" });
|
|
1287
|
+
}
|
|
1288
|
+
const delegations = await verifyReceiptDelegations(receipt);
|
|
1289
|
+
const delegationErrors = delegations.filter((d) => !d.valid);
|
|
1290
|
+
for (const d of delegationErrors) {
|
|
1291
|
+
errors.push({
|
|
1292
|
+
message: `Delegation ${d.receipt?.task_id ?? "unknown"}: verification failed`,
|
|
1293
|
+
path: `delegation_receipts`
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
return {
|
|
1297
|
+
type: "receipt",
|
|
1298
|
+
valid: sigResult.valid && delegationErrors.length === 0,
|
|
1299
|
+
receipt,
|
|
1300
|
+
signer: signerDid,
|
|
1301
|
+
...delegations.length > 0 ? { delegations } : {},
|
|
1302
|
+
...errors.length > 0 ? { errors } : {}
|
|
1303
|
+
};
|
|
555
1304
|
}
|
|
556
1305
|
async function verifyReceiptDelegations(receipt) {
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
1306
|
+
if (!receipt.delegation_receipts || receipt.delegation_receipts.length === 0) {
|
|
1307
|
+
return [];
|
|
1308
|
+
}
|
|
1309
|
+
return Promise.all(receipt.delegation_receipts.map((dr) => verifyReceipt(dr)));
|
|
561
1310
|
}
|
|
562
|
-
// ===========================================================================
|
|
563
|
-
// Verifiable Credential verification (eddsa-jcs-2022)
|
|
564
|
-
// ===========================================================================
|
|
565
1311
|
async function verifyDataIntegrity(document, proof) {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
catch {
|
|
597
|
-
return false;
|
|
598
|
-
}
|
|
599
|
-
try {
|
|
600
|
-
return await ed.verifyAsync(signature, combined, publicKey);
|
|
601
|
-
}
|
|
602
|
-
catch {
|
|
603
|
-
return false;
|
|
604
|
-
}
|
|
1312
|
+
if (proof.type !== "DataIntegrityProof" || proof.cryptosuite !== "eddsa-jcs-2022") {
|
|
1313
|
+
return false;
|
|
1314
|
+
}
|
|
1315
|
+
const did = proof.verificationMethod.split("#")[0];
|
|
1316
|
+
let publicKey;
|
|
1317
|
+
try {
|
|
1318
|
+
publicKey = didKeyToPublicKey(did);
|
|
1319
|
+
} catch {
|
|
1320
|
+
return false;
|
|
1321
|
+
}
|
|
1322
|
+
const { proofValue, ...proofOptions } = proof;
|
|
1323
|
+
const encoder = new TextEncoder();
|
|
1324
|
+
const proofHash = await sha256(encoder.encode(canonicalJson(proofOptions)));
|
|
1325
|
+
const { proof: _proof, ...docWithoutProof } = document;
|
|
1326
|
+
const docHash = await sha256(encoder.encode(canonicalJson(docWithoutProof)));
|
|
1327
|
+
const combined = new Uint8Array(proofHash.length + docHash.length);
|
|
1328
|
+
combined.set(proofHash);
|
|
1329
|
+
combined.set(docHash, proofHash.length);
|
|
1330
|
+
if (!proofValue.startsWith("z")) return false;
|
|
1331
|
+
let signature;
|
|
1332
|
+
try {
|
|
1333
|
+
signature = base58btcDecode(proofValue.slice(1));
|
|
1334
|
+
} catch {
|
|
1335
|
+
return false;
|
|
1336
|
+
}
|
|
1337
|
+
try {
|
|
1338
|
+
return await verifyAsync(signature, combined, publicKey);
|
|
1339
|
+
} catch {
|
|
1340
|
+
return false;
|
|
1341
|
+
}
|
|
605
1342
|
}
|
|
606
|
-
|
|
1343
|
+
var DEFAULT_CLOCK_SKEW_SECONDS = 60;
|
|
607
1344
|
async function verifyCredential(vc, clockSkewSeconds = DEFAULT_CLOCK_SKEW_SECONDS) {
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
errors.push({ message: "Credential has expired", path: "validUntil" });
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
// Verify proof
|
|
620
|
-
const proofValid = await verifyDataIntegrity(vc, vc.proof);
|
|
621
|
-
if (!proofValid) {
|
|
622
|
-
errors.push({ message: "Credential proof verification failed", path: "proof" });
|
|
1345
|
+
const errors = [];
|
|
1346
|
+
let expired = false;
|
|
1347
|
+
if (vc.validUntil) {
|
|
1348
|
+
const expiresAt = new Date(vc.validUntil).getTime();
|
|
1349
|
+
const skewMs = clockSkewSeconds * 1e3;
|
|
1350
|
+
if (Date.now() > expiresAt + skewMs) {
|
|
1351
|
+
expired = true;
|
|
1352
|
+
errors.push({ message: "Credential has expired", path: "validUntil" });
|
|
623
1353
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
1354
|
+
}
|
|
1355
|
+
const proofValid = await verifyDataIntegrity(vc, vc.proof);
|
|
1356
|
+
if (!proofValid) {
|
|
1357
|
+
errors.push({ message: "Credential proof verification failed", path: "proof" });
|
|
1358
|
+
}
|
|
1359
|
+
const issuerDid = typeof vc.issuer === "string" ? vc.issuer : void 0;
|
|
1360
|
+
const subjectId = vc.credentialSubject?.id;
|
|
1361
|
+
return {
|
|
1362
|
+
type: "credential",
|
|
1363
|
+
valid: proofValid && !expired,
|
|
1364
|
+
credential: vc,
|
|
1365
|
+
issuer: issuerDid,
|
|
1366
|
+
subject: subjectId,
|
|
1367
|
+
expired,
|
|
1368
|
+
...errors.length > 0 ? { errors } : {}
|
|
1369
|
+
};
|
|
636
1370
|
}
|
|
637
|
-
// ===========================================================================
|
|
638
|
-
// Verifiable Presentation verification
|
|
639
|
-
// ===========================================================================
|
|
640
1371
|
async function verifyPresentation(vp, clockSkewSeconds = DEFAULT_CLOCK_SKEW_SECONDS) {
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
1372
|
+
const errors = [];
|
|
1373
|
+
const envelopeValid = await verifyDataIntegrity(
|
|
1374
|
+
vp,
|
|
1375
|
+
vp.proof
|
|
1376
|
+
);
|
|
1377
|
+
if (!envelopeValid) {
|
|
1378
|
+
errors.push({ message: "Presentation proof verification failed", path: "proof" });
|
|
1379
|
+
}
|
|
1380
|
+
const credentialResults = [];
|
|
1381
|
+
for (let i = 0; i < vp.verifiableCredential.length; i++) {
|
|
1382
|
+
const vc = vp.verifiableCredential[i];
|
|
1383
|
+
const vcResult = await verifyCredential(vc, clockSkewSeconds);
|
|
1384
|
+
credentialResults.push(vcResult);
|
|
1385
|
+
if (!vcResult.valid) {
|
|
1386
|
+
errors.push({
|
|
1387
|
+
message: `Credential ${i} verification failed`,
|
|
1388
|
+
path: `verifiableCredential[${i}]`
|
|
1389
|
+
});
|
|
659
1390
|
}
|
|
660
|
-
|
|
1391
|
+
}
|
|
1392
|
+
const allValid = envelopeValid && credentialResults.every((c) => c.valid);
|
|
1393
|
+
return {
|
|
1394
|
+
type: "presentation",
|
|
1395
|
+
valid: allValid,
|
|
1396
|
+
presentation: vp,
|
|
1397
|
+
holder: vp.holder,
|
|
1398
|
+
credentials: credentialResults,
|
|
1399
|
+
...errors.length > 0 ? { errors } : {}
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
async function verify(artifact, options) {
|
|
1403
|
+
const detected = detectArtifactType(artifact);
|
|
1404
|
+
if (detected === null) {
|
|
1405
|
+
const fallbackType = options?.expectedType ?? "identity";
|
|
661
1406
|
return {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
1407
|
+
type: fallbackType,
|
|
1408
|
+
valid: false,
|
|
1409
|
+
...fallbackType === "identity" ? { identity: null } : {},
|
|
1410
|
+
...fallbackType === "receipt" ? { receipt: null } : {},
|
|
1411
|
+
...fallbackType === "credential" ? { credential: null } : {},
|
|
1412
|
+
...fallbackType === "presentation" ? { presentation: null } : {},
|
|
1413
|
+
errors: [{ message: "Unrecognized artifact format" }]
|
|
668
1414
|
};
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
// Public API
|
|
672
|
-
// ===========================================================================
|
|
673
|
-
/**
|
|
674
|
-
* Verify any Motebit artifact: identity file, execution receipt,
|
|
675
|
-
* verifiable credential, or verifiable presentation.
|
|
676
|
-
*
|
|
677
|
-
* Accepts strings (identity files, JSON) or parsed objects (receipts,
|
|
678
|
-
* credentials, presentations). Detects the artifact type automatically.
|
|
679
|
-
*
|
|
680
|
-
* Use `options.expectedType` to fail fast if the artifact doesn't match
|
|
681
|
-
* the expected type.
|
|
682
|
-
*
|
|
683
|
-
* @example
|
|
684
|
-
* ```ts
|
|
685
|
-
* import { verify } from "@motebit/verify";
|
|
686
|
-
*
|
|
687
|
-
* // Identity file (string)
|
|
688
|
-
* const r1 = await verify(identityFileContent);
|
|
689
|
-
* if (r1.type === "identity" && r1.valid) console.log(r1.did);
|
|
690
|
-
*
|
|
691
|
-
* // Execution receipt (object or JSON string)
|
|
692
|
-
* const r2 = await verify(receipt, { expectedType: "receipt" });
|
|
693
|
-
* if (r2.type === "receipt" && r2.valid) console.log(r2.signer);
|
|
694
|
-
*
|
|
695
|
-
* // Verifiable credential
|
|
696
|
-
* const r3 = await verify(credential);
|
|
697
|
-
* if (r3.type === "credential" && r3.valid) console.log(r3.issuer);
|
|
698
|
-
* ```
|
|
699
|
-
*/
|
|
700
|
-
export async function verify(artifact, options) {
|
|
701
|
-
const detected = detectArtifactType(artifact);
|
|
702
|
-
if (detected === null) {
|
|
703
|
-
// Return a generic failure — use identity as the default type for backward compat
|
|
704
|
-
const fallbackType = options?.expectedType ?? "identity";
|
|
705
|
-
return {
|
|
706
|
-
type: fallbackType,
|
|
707
|
-
valid: false,
|
|
708
|
-
...(fallbackType === "identity" ? { identity: null } : {}),
|
|
709
|
-
...(fallbackType === "receipt" ? { receipt: null } : {}),
|
|
710
|
-
...(fallbackType === "credential" ? { credential: null } : {}),
|
|
711
|
-
...(fallbackType === "presentation" ? { presentation: null } : {}),
|
|
712
|
-
errors: [{ message: "Unrecognized artifact format" }],
|
|
713
|
-
};
|
|
714
|
-
}
|
|
715
|
-
if (options?.expectedType && options.expectedType !== detected) {
|
|
716
|
-
return {
|
|
717
|
-
type: detected,
|
|
718
|
-
valid: false,
|
|
719
|
-
...(detected === "identity" ? { identity: null } : {}),
|
|
720
|
-
...(detected === "receipt" ? { receipt: null } : {}),
|
|
721
|
-
...(detected === "credential" ? { credential: null } : {}),
|
|
722
|
-
...(detected === "presentation" ? { presentation: null } : {}),
|
|
723
|
-
errors: [{ message: `Expected type "${options.expectedType}" but detected "${detected}"` }],
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
// Parse JSON strings into objects for non-identity types
|
|
727
|
-
let resolved = artifact;
|
|
728
|
-
if (typeof artifact === "string" && detected !== "identity") {
|
|
729
|
-
try {
|
|
730
|
-
resolved = JSON.parse(artifact);
|
|
731
|
-
}
|
|
732
|
-
catch {
|
|
733
|
-
return {
|
|
734
|
-
type: detected,
|
|
735
|
-
valid: false,
|
|
736
|
-
...(detected === "receipt" ? { receipt: null } : {}),
|
|
737
|
-
...(detected === "credential" ? { credential: null } : {}),
|
|
738
|
-
...(detected === "presentation" ? { presentation: null } : {}),
|
|
739
|
-
errors: [{ message: "Failed to parse JSON" }],
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
switch (detected) {
|
|
744
|
-
case "identity":
|
|
745
|
-
return verifyIdentity(resolved);
|
|
746
|
-
case "receipt":
|
|
747
|
-
return verifyReceipt(resolved);
|
|
748
|
-
case "credential":
|
|
749
|
-
return verifyCredential(resolved, options?.clockSkewSeconds);
|
|
750
|
-
case "presentation":
|
|
751
|
-
return verifyPresentation(resolved, options?.clockSkewSeconds);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Verify a motebit.md identity file. Backward-compatible with pre-0.4.0.
|
|
756
|
-
*
|
|
757
|
-
* @deprecated Use `verify(content)` instead — it handles all artifact types.
|
|
758
|
-
*/
|
|
759
|
-
export async function verifyIdentityFile(content) {
|
|
760
|
-
const result = await verifyIdentity(content);
|
|
1415
|
+
}
|
|
1416
|
+
if (options?.expectedType && options.expectedType !== detected) {
|
|
761
1417
|
return {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
1418
|
+
type: detected,
|
|
1419
|
+
valid: false,
|
|
1420
|
+
...detected === "identity" ? { identity: null } : {},
|
|
1421
|
+
...detected === "receipt" ? { receipt: null } : {},
|
|
1422
|
+
...detected === "credential" ? { credential: null } : {},
|
|
1423
|
+
...detected === "presentation" ? { presentation: null } : {},
|
|
1424
|
+
errors: [{ message: `Expected type "${options.expectedType}" but detected "${detected}"` }]
|
|
767
1425
|
};
|
|
1426
|
+
}
|
|
1427
|
+
let resolved = artifact;
|
|
1428
|
+
if (typeof artifact === "string" && detected !== "identity") {
|
|
1429
|
+
try {
|
|
1430
|
+
resolved = JSON.parse(artifact);
|
|
1431
|
+
} catch {
|
|
1432
|
+
return {
|
|
1433
|
+
type: detected,
|
|
1434
|
+
valid: false,
|
|
1435
|
+
...detected === "receipt" ? { receipt: null } : {},
|
|
1436
|
+
...detected === "credential" ? { credential: null } : {},
|
|
1437
|
+
...detected === "presentation" ? { presentation: null } : {},
|
|
1438
|
+
errors: [{ message: "Failed to parse JSON" }]
|
|
1439
|
+
};
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
switch (detected) {
|
|
1443
|
+
case "identity":
|
|
1444
|
+
return verifyIdentity(resolved);
|
|
1445
|
+
case "receipt":
|
|
1446
|
+
return verifyReceipt(resolved);
|
|
1447
|
+
case "credential":
|
|
1448
|
+
return verifyCredential(resolved, options?.clockSkewSeconds);
|
|
1449
|
+
case "presentation":
|
|
1450
|
+
return verifyPresentation(resolved, options?.clockSkewSeconds);
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
async function verifyIdentityFile(content) {
|
|
1454
|
+
const result = await verifyIdentity(content);
|
|
1455
|
+
return {
|
|
1456
|
+
valid: result.valid,
|
|
1457
|
+
identity: result.identity,
|
|
1458
|
+
did: result.did,
|
|
1459
|
+
error: result.errors?.[0]?.message,
|
|
1460
|
+
succession: result.succession
|
|
1461
|
+
};
|
|
768
1462
|
}
|
|
769
|
-
|
|
1463
|
+
export {
|
|
1464
|
+
parse,
|
|
1465
|
+
verify,
|
|
1466
|
+
verifyIdentityFile
|
|
1467
|
+
};
|
|
1468
|
+
/*! Bundled license information:
|
|
1469
|
+
|
|
1470
|
+
@noble/ed25519/index.js:
|
|
1471
|
+
(*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
|
|
1472
|
+
|
|
1473
|
+
@noble/hashes/esm/utils.js:
|
|
1474
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
1475
|
+
*/
|