@bandeira-tech/b3nd-web 0.2.0 → 0.2.2
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/apps/mod.d.ts +26 -17
- package/dist/apps/mod.js +1 -1
- package/dist/{chunk-2D2RT2DW.js → chunk-2VOR4VLG.js} +118 -34
- package/dist/{chunk-XH4OLKBV.js → chunk-7U5JDFQW.js} +2 -5
- package/dist/chunk-K3ZSSVHR.js +615 -0
- package/dist/{chunk-PMBS2GFA.js → chunk-LFUC4ETD.js} +9 -12
- package/dist/{chunk-C2ZIFM22.js → chunk-T43IWAQK.js} +17 -24
- package/dist/{chunk-QHDBFVLU.js → chunk-VAZUCGED.js} +24 -22
- package/dist/clients/http/mod.d.ts +1 -1
- package/dist/clients/http/mod.js +1 -1
- package/dist/clients/local-storage/mod.d.ts +1 -1
- package/dist/clients/local-storage/mod.js +1 -1
- package/dist/clients/websocket/mod.d.ts +1 -1
- package/dist/clients/websocket/mod.js +1 -1
- package/dist/encrypt/mod.d.ts +1 -1
- package/dist/encrypt/mod.js +29 -3
- package/dist/mod-D02790g_.d.ts +241 -0
- package/dist/src/mod.web.d.ts +2 -2
- package/dist/src/mod.web.js +6 -6
- package/dist/{types-Bw0Boe0n.d.ts → types-oQCx3U-_.d.ts} +2 -2
- package/dist/wallet/mod.d.ts +61 -10
- package/dist/wallet/mod.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-G6JDROB4.js +0 -327
- package/dist/mod-DHjjiF1o.d.ts +0 -111
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-MLKGABMK.js";
|
|
4
|
+
|
|
5
|
+
// encrypt/mod.ts
|
|
6
|
+
var mod_exports = {};
|
|
7
|
+
__export(mod_exports, {
|
|
8
|
+
IdentityKey: () => IdentityKey,
|
|
9
|
+
PrivateEncryptionKey: () => PrivateEncryptionKey,
|
|
10
|
+
PublicEncryptionKey: () => PublicEncryptionKey,
|
|
11
|
+
SecretEncryptionKey: () => SecretEncryptionKey,
|
|
12
|
+
createAuthenticatedMessage: () => createAuthenticatedMessage,
|
|
13
|
+
createAuthenticatedMessageWithHex: () => createAuthenticatedMessageWithHex,
|
|
14
|
+
createSignedEncryptedMessage: () => createSignedEncryptedMessage,
|
|
15
|
+
createSignedSymmetricMessage: () => createSignedSymmetricMessage,
|
|
16
|
+
decrypt: () => decrypt,
|
|
17
|
+
decryptSymmetric: () => decryptSymmetric,
|
|
18
|
+
decryptWithHex: () => decryptWithHex,
|
|
19
|
+
deriveKeyFromSeed: () => deriveKeyFromSeed,
|
|
20
|
+
encrypt: () => encrypt,
|
|
21
|
+
encryptSymmetric: () => encryptSymmetric,
|
|
22
|
+
exportPrivateKeyPem: () => exportPrivateKeyPem,
|
|
23
|
+
generateEncryptionKeyPair: () => generateEncryptionKeyPair,
|
|
24
|
+
generateNonce: () => generateNonce,
|
|
25
|
+
generateRandomData: () => generateRandomData,
|
|
26
|
+
generateSigningKeyPair: () => generateSigningKeyPair,
|
|
27
|
+
pemToCryptoKey: () => pemToCryptoKey,
|
|
28
|
+
sign: () => sign,
|
|
29
|
+
signPayload: () => signPayload,
|
|
30
|
+
signWithHex: () => signWithHex,
|
|
31
|
+
verify: () => verify,
|
|
32
|
+
verifyAndDecryptMessage: () => verifyAndDecryptMessage,
|
|
33
|
+
verifyPayload: () => verifyPayload
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// shared/encoding.ts
|
|
37
|
+
function encodeHex(bytes) {
|
|
38
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
39
|
+
}
|
|
40
|
+
function decodeHex(hex) {
|
|
41
|
+
if (hex.length % 2 !== 0) {
|
|
42
|
+
throw new Error("Invalid hex input");
|
|
43
|
+
}
|
|
44
|
+
const buffer = new ArrayBuffer(hex.length / 2);
|
|
45
|
+
const bytes = new Uint8Array(buffer);
|
|
46
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
47
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
48
|
+
}
|
|
49
|
+
return bytes;
|
|
50
|
+
}
|
|
51
|
+
function encodeBase64(bytes) {
|
|
52
|
+
const buf = typeof globalThis !== "undefined" && globalThis.Buffer || void 0;
|
|
53
|
+
if (buf) {
|
|
54
|
+
return buf.from(bytes).toString("base64");
|
|
55
|
+
}
|
|
56
|
+
let binary = "";
|
|
57
|
+
bytes.forEach((b) => binary += String.fromCharCode(b));
|
|
58
|
+
return btoa(binary);
|
|
59
|
+
}
|
|
60
|
+
function decodeBase64(b64) {
|
|
61
|
+
const buf = typeof globalThis !== "undefined" && globalThis.Buffer || void 0;
|
|
62
|
+
if (buf) {
|
|
63
|
+
return new Uint8Array(buf.from(b64, "base64"));
|
|
64
|
+
}
|
|
65
|
+
const binary = atob(b64);
|
|
66
|
+
const bytes = new Uint8Array(binary.length);
|
|
67
|
+
for (let i = 0; i < binary.length; i++) {
|
|
68
|
+
bytes[i] = binary.charCodeAt(i);
|
|
69
|
+
}
|
|
70
|
+
return bytes;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// encrypt/mod.ts
|
|
74
|
+
var IdentityKey = class _IdentityKey {
|
|
75
|
+
constructor(privateKey, publicKeyHex) {
|
|
76
|
+
this.privateKey = privateKey;
|
|
77
|
+
this.publicKeyHex = publicKeyHex;
|
|
78
|
+
}
|
|
79
|
+
static async generate() {
|
|
80
|
+
const pair = await generateSigningKeyPair();
|
|
81
|
+
const privateKeyPem = await exportPrivateKeyPem(pair.privateKey, "PRIVATE KEY");
|
|
82
|
+
return {
|
|
83
|
+
key: new _IdentityKey(pair.privateKey, pair.publicKeyHex),
|
|
84
|
+
privateKeyPem,
|
|
85
|
+
publicKeyHex: pair.publicKeyHex
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
static async fromPem(pem, publicKeyHex) {
|
|
89
|
+
const privateKey = await pemToCryptoKey(pem, "Ed25519");
|
|
90
|
+
return new _IdentityKey(privateKey, publicKeyHex);
|
|
91
|
+
}
|
|
92
|
+
static async fromHex(params) {
|
|
93
|
+
const privateKeyBytes = decodeHex(params.privateKeyHex).buffer;
|
|
94
|
+
const privateKey = await crypto.subtle.importKey(
|
|
95
|
+
"pkcs8",
|
|
96
|
+
privateKeyBytes,
|
|
97
|
+
{ name: "Ed25519", namedCurve: "Ed25519" },
|
|
98
|
+
false,
|
|
99
|
+
["sign"]
|
|
100
|
+
);
|
|
101
|
+
return new _IdentityKey(privateKey, params.publicKeyHex);
|
|
102
|
+
}
|
|
103
|
+
async sign(payload) {
|
|
104
|
+
return await sign(this.privateKey, payload);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var PublicEncryptionKey = class _PublicEncryptionKey {
|
|
108
|
+
constructor(publicKeyHex, publicKey) {
|
|
109
|
+
this.publicKeyHex = publicKeyHex;
|
|
110
|
+
this.publicKey = publicKey;
|
|
111
|
+
}
|
|
112
|
+
static async fromHex(publicKeyHex) {
|
|
113
|
+
const publicKeyBytes = decodeHex(publicKeyHex).buffer;
|
|
114
|
+
const publicKey = await crypto.subtle.importKey(
|
|
115
|
+
"raw",
|
|
116
|
+
publicKeyBytes,
|
|
117
|
+
{ name: "X25519", namedCurve: "X25519" },
|
|
118
|
+
false,
|
|
119
|
+
[]
|
|
120
|
+
);
|
|
121
|
+
return new _PublicEncryptionKey(publicKeyHex, publicKey);
|
|
122
|
+
}
|
|
123
|
+
static async generatePair() {
|
|
124
|
+
const pair = await generateEncryptionKeyPair();
|
|
125
|
+
const privateKeyBytes = new Uint8Array(
|
|
126
|
+
await crypto.subtle.exportKey("pkcs8", pair.privateKey)
|
|
127
|
+
);
|
|
128
|
+
return {
|
|
129
|
+
publicKey: new _PublicEncryptionKey(pair.publicKeyHex, pair.publicKey),
|
|
130
|
+
privateKeyHex: encodeHex(privateKeyBytes)
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
async encrypt(data) {
|
|
134
|
+
return await encrypt(data, this.publicKeyHex);
|
|
135
|
+
}
|
|
136
|
+
toHex() {
|
|
137
|
+
return this.publicKeyHex;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var SecretEncryptionKey = class _SecretEncryptionKey {
|
|
141
|
+
constructor(keyHex) {
|
|
142
|
+
this.keyHex = keyHex;
|
|
143
|
+
}
|
|
144
|
+
static async fromSecret(params) {
|
|
145
|
+
const keyHex = await deriveKeyFromSeed(
|
|
146
|
+
params.secret,
|
|
147
|
+
params.salt,
|
|
148
|
+
params.iterations ?? 1e5
|
|
149
|
+
);
|
|
150
|
+
return new _SecretEncryptionKey(keyHex);
|
|
151
|
+
}
|
|
152
|
+
static fromHex(keyHex) {
|
|
153
|
+
return new _SecretEncryptionKey(keyHex);
|
|
154
|
+
}
|
|
155
|
+
async encrypt(data) {
|
|
156
|
+
return await encryptSymmetric(data, this.keyHex);
|
|
157
|
+
}
|
|
158
|
+
async decrypt(payload) {
|
|
159
|
+
return await decryptSymmetric(payload, this.keyHex);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
var PrivateEncryptionKey = class _PrivateEncryptionKey {
|
|
163
|
+
constructor(privateKey, privateKeyHex, publicKeyHex) {
|
|
164
|
+
this.privateKey = privateKey;
|
|
165
|
+
this.privateKeyHex = privateKeyHex;
|
|
166
|
+
this.publicKeyHex = publicKeyHex;
|
|
167
|
+
}
|
|
168
|
+
static async fromHex(params) {
|
|
169
|
+
const { privateKeyHex, publicKeyHex } = params;
|
|
170
|
+
const privateKeyBytes = decodeHex(privateKeyHex).buffer;
|
|
171
|
+
const privateKey = await crypto.subtle.importKey(
|
|
172
|
+
"pkcs8",
|
|
173
|
+
privateKeyBytes,
|
|
174
|
+
{ name: "X25519", namedCurve: "X25519" },
|
|
175
|
+
false,
|
|
176
|
+
["deriveBits"]
|
|
177
|
+
);
|
|
178
|
+
return new _PrivateEncryptionKey(privateKey, privateKeyHex, publicKeyHex);
|
|
179
|
+
}
|
|
180
|
+
static async generatePair() {
|
|
181
|
+
const pair = await generateEncryptionKeyPair();
|
|
182
|
+
const privateKeyBytes = new Uint8Array(
|
|
183
|
+
await crypto.subtle.exportKey("pkcs8", pair.privateKey)
|
|
184
|
+
);
|
|
185
|
+
const privateKeyHex = encodeHex(privateKeyBytes);
|
|
186
|
+
const publicKey = new PublicEncryptionKey(pair.publicKeyHex, pair.publicKey);
|
|
187
|
+
return {
|
|
188
|
+
privateKey: new _PrivateEncryptionKey(pair.privateKey, privateKeyHex, pair.publicKeyHex),
|
|
189
|
+
publicKey
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
toPublic() {
|
|
193
|
+
return new PublicEncryptionKey(this.publicKeyHex, null);
|
|
194
|
+
}
|
|
195
|
+
async decrypt(payload) {
|
|
196
|
+
return await decrypt(payload, this.privateKey);
|
|
197
|
+
}
|
|
198
|
+
toHex() {
|
|
199
|
+
return this.privateKeyHex;
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
async function pemToCryptoKey(pem, algorithm) {
|
|
203
|
+
const lines = pem.split("\n").map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("---"));
|
|
204
|
+
if (lines.length === 0) {
|
|
205
|
+
throw new Error("Invalid PEM: no key data");
|
|
206
|
+
}
|
|
207
|
+
const base64 = lines.join("");
|
|
208
|
+
const binary = atob(base64);
|
|
209
|
+
const bytes = new Uint8Array(binary.length);
|
|
210
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
211
|
+
const buffer = bytes.buffer.slice(
|
|
212
|
+
bytes.byteOffset,
|
|
213
|
+
bytes.byteOffset + bytes.byteLength
|
|
214
|
+
);
|
|
215
|
+
if (algorithm === "Ed25519") {
|
|
216
|
+
return await crypto.subtle.importKey(
|
|
217
|
+
"pkcs8",
|
|
218
|
+
buffer,
|
|
219
|
+
{ name: "Ed25519", namedCurve: "Ed25519" },
|
|
220
|
+
false,
|
|
221
|
+
["sign"]
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
return await crypto.subtle.importKey(
|
|
225
|
+
"pkcs8",
|
|
226
|
+
buffer,
|
|
227
|
+
{ name: "X25519", namedCurve: "X25519" },
|
|
228
|
+
false,
|
|
229
|
+
["deriveBits"]
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
async function generateSigningKeyPair() {
|
|
233
|
+
const keyPair = await crypto.subtle.generateKey(
|
|
234
|
+
{
|
|
235
|
+
name: "Ed25519",
|
|
236
|
+
namedCurve: "Ed25519"
|
|
237
|
+
},
|
|
238
|
+
true,
|
|
239
|
+
["sign", "verify"]
|
|
240
|
+
);
|
|
241
|
+
const publicKeyBytes = await crypto.subtle.exportKey("raw", keyPair.publicKey);
|
|
242
|
+
const privateKeyBytes = await crypto.subtle.exportKey(
|
|
243
|
+
"pkcs8",
|
|
244
|
+
keyPair.privateKey
|
|
245
|
+
);
|
|
246
|
+
return {
|
|
247
|
+
publicKey: keyPair.publicKey,
|
|
248
|
+
privateKey: keyPair.privateKey,
|
|
249
|
+
publicKeyHex: encodeHex(new Uint8Array(publicKeyBytes)),
|
|
250
|
+
privateKeyHex: encodeHex(new Uint8Array(privateKeyBytes))
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
async function generateEncryptionKeyPair() {
|
|
254
|
+
const keyPair = await crypto.subtle.generateKey(
|
|
255
|
+
{
|
|
256
|
+
name: "X25519",
|
|
257
|
+
namedCurve: "X25519"
|
|
258
|
+
},
|
|
259
|
+
true,
|
|
260
|
+
["deriveBits"]
|
|
261
|
+
);
|
|
262
|
+
const publicKeyBytes = await crypto.subtle.exportKey("raw", keyPair.publicKey);
|
|
263
|
+
return {
|
|
264
|
+
publicKey: keyPair.publicKey,
|
|
265
|
+
privateKey: keyPair.privateKey,
|
|
266
|
+
publicKeyHex: encodeHex(new Uint8Array(publicKeyBytes))
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
async function sign(privateKey, payload) {
|
|
270
|
+
const encoder = new TextEncoder();
|
|
271
|
+
const data = encoder.encode(JSON.stringify(payload));
|
|
272
|
+
const signature = await crypto.subtle.sign("Ed25519", privateKey, data);
|
|
273
|
+
return encodeHex(new Uint8Array(signature));
|
|
274
|
+
}
|
|
275
|
+
async function signWithHex(privateKeyHex, payload) {
|
|
276
|
+
const privateKeyBytes = decodeHex(privateKeyHex).buffer;
|
|
277
|
+
const privateKey = await crypto.subtle.importKey(
|
|
278
|
+
"pkcs8",
|
|
279
|
+
privateKeyBytes,
|
|
280
|
+
{
|
|
281
|
+
name: "Ed25519",
|
|
282
|
+
namedCurve: "Ed25519"
|
|
283
|
+
},
|
|
284
|
+
false,
|
|
285
|
+
["sign"]
|
|
286
|
+
);
|
|
287
|
+
return await sign(privateKey, payload);
|
|
288
|
+
}
|
|
289
|
+
async function verify(publicKeyHex, signatureHex, payload) {
|
|
290
|
+
try {
|
|
291
|
+
const publicKeyBytes = decodeHex(publicKeyHex).buffer;
|
|
292
|
+
const publicKey = await crypto.subtle.importKey(
|
|
293
|
+
"raw",
|
|
294
|
+
publicKeyBytes,
|
|
295
|
+
{
|
|
296
|
+
name: "Ed25519",
|
|
297
|
+
namedCurve: "Ed25519"
|
|
298
|
+
},
|
|
299
|
+
false,
|
|
300
|
+
["verify"]
|
|
301
|
+
);
|
|
302
|
+
const encoder = new TextEncoder();
|
|
303
|
+
const data = encoder.encode(JSON.stringify(payload));
|
|
304
|
+
const signatureBytes = decodeHex(signatureHex).buffer;
|
|
305
|
+
return await crypto.subtle.verify(
|
|
306
|
+
"Ed25519",
|
|
307
|
+
publicKey,
|
|
308
|
+
signatureBytes,
|
|
309
|
+
data
|
|
310
|
+
);
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error("Verification error:", error);
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async function encrypt(data, recipientPublicKeyHex) {
|
|
317
|
+
const ephemeralKeyPair = await generateEncryptionKeyPair();
|
|
318
|
+
const recipientPublicKeyBytes = decodeHex(recipientPublicKeyHex).buffer;
|
|
319
|
+
const recipientPublicKey = await crypto.subtle.importKey(
|
|
320
|
+
"raw",
|
|
321
|
+
recipientPublicKeyBytes,
|
|
322
|
+
{
|
|
323
|
+
name: "X25519",
|
|
324
|
+
namedCurve: "X25519"
|
|
325
|
+
},
|
|
326
|
+
false,
|
|
327
|
+
[]
|
|
328
|
+
);
|
|
329
|
+
const sharedSecret = await crypto.subtle.deriveBits(
|
|
330
|
+
{
|
|
331
|
+
name: "X25519",
|
|
332
|
+
public: recipientPublicKey
|
|
333
|
+
},
|
|
334
|
+
ephemeralKeyPair.privateKey,
|
|
335
|
+
256
|
|
336
|
+
);
|
|
337
|
+
const aesKey = await crypto.subtle.importKey(
|
|
338
|
+
"raw",
|
|
339
|
+
sharedSecret,
|
|
340
|
+
{
|
|
341
|
+
name: "AES-GCM",
|
|
342
|
+
length: 256
|
|
343
|
+
},
|
|
344
|
+
false,
|
|
345
|
+
["encrypt"]
|
|
346
|
+
);
|
|
347
|
+
const nonce = crypto.getRandomValues(new Uint8Array(12));
|
|
348
|
+
const encoder = new TextEncoder();
|
|
349
|
+
const plaintext = encoder.encode(JSON.stringify(data));
|
|
350
|
+
const ciphertext = await crypto.subtle.encrypt(
|
|
351
|
+
{
|
|
352
|
+
name: "AES-GCM",
|
|
353
|
+
iv: nonce
|
|
354
|
+
},
|
|
355
|
+
aesKey,
|
|
356
|
+
plaintext
|
|
357
|
+
);
|
|
358
|
+
return {
|
|
359
|
+
data: encodeBase64(new Uint8Array(ciphertext)),
|
|
360
|
+
nonce: encodeBase64(nonce),
|
|
361
|
+
ephemeralPublicKey: ephemeralKeyPair.publicKeyHex
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
async function decrypt(encryptedPayload, recipientPrivateKey) {
|
|
365
|
+
if (!encryptedPayload.ephemeralPublicKey) {
|
|
366
|
+
throw new Error("Missing ephemeral public key");
|
|
367
|
+
}
|
|
368
|
+
const ephemeralPublicKeyBytes = decodeHex(
|
|
369
|
+
encryptedPayload.ephemeralPublicKey
|
|
370
|
+
).buffer;
|
|
371
|
+
const ephemeralPublicKey = await crypto.subtle.importKey(
|
|
372
|
+
"raw",
|
|
373
|
+
ephemeralPublicKeyBytes,
|
|
374
|
+
{
|
|
375
|
+
name: "X25519",
|
|
376
|
+
namedCurve: "X25519"
|
|
377
|
+
},
|
|
378
|
+
false,
|
|
379
|
+
[]
|
|
380
|
+
);
|
|
381
|
+
const sharedSecret = await crypto.subtle.deriveBits(
|
|
382
|
+
{
|
|
383
|
+
name: "X25519",
|
|
384
|
+
public: ephemeralPublicKey
|
|
385
|
+
},
|
|
386
|
+
recipientPrivateKey,
|
|
387
|
+
256
|
|
388
|
+
);
|
|
389
|
+
const aesKey = await crypto.subtle.importKey(
|
|
390
|
+
"raw",
|
|
391
|
+
sharedSecret,
|
|
392
|
+
{
|
|
393
|
+
name: "AES-GCM",
|
|
394
|
+
length: 256
|
|
395
|
+
},
|
|
396
|
+
false,
|
|
397
|
+
["decrypt"]
|
|
398
|
+
);
|
|
399
|
+
const ciphertext = new Uint8Array(decodeBase64(encryptedPayload.data));
|
|
400
|
+
const nonce = new Uint8Array(decodeBase64(encryptedPayload.nonce));
|
|
401
|
+
const plaintext = await crypto.subtle.decrypt(
|
|
402
|
+
{
|
|
403
|
+
name: "AES-GCM",
|
|
404
|
+
iv: nonce
|
|
405
|
+
},
|
|
406
|
+
aesKey,
|
|
407
|
+
ciphertext
|
|
408
|
+
);
|
|
409
|
+
const decoder = new TextDecoder();
|
|
410
|
+
const json = decoder.decode(plaintext);
|
|
411
|
+
return JSON.parse(json);
|
|
412
|
+
}
|
|
413
|
+
async function decryptWithHex(encryptedPayload, recipientPrivateKeyHex) {
|
|
414
|
+
const privateKeyBytes = decodeHex(recipientPrivateKeyHex).buffer;
|
|
415
|
+
const privateKey = await crypto.subtle.importKey(
|
|
416
|
+
"raw",
|
|
417
|
+
privateKeyBytes,
|
|
418
|
+
{
|
|
419
|
+
name: "X25519",
|
|
420
|
+
namedCurve: "X25519"
|
|
421
|
+
},
|
|
422
|
+
false,
|
|
423
|
+
["deriveBits"]
|
|
424
|
+
);
|
|
425
|
+
return await decrypt(encryptedPayload, privateKey);
|
|
426
|
+
}
|
|
427
|
+
async function createAuthenticatedMessage(payload, signers) {
|
|
428
|
+
const auth = await Promise.all(
|
|
429
|
+
signers.map(async (signer) => {
|
|
430
|
+
const signature = await sign(signer.privateKey, payload);
|
|
431
|
+
return {
|
|
432
|
+
pubkey: signer.publicKeyHex,
|
|
433
|
+
signature
|
|
434
|
+
};
|
|
435
|
+
})
|
|
436
|
+
);
|
|
437
|
+
return {
|
|
438
|
+
auth,
|
|
439
|
+
payload
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
async function createAuthenticatedMessageWithHex(payload, pubkeyHex, privateKeyHex) {
|
|
443
|
+
const signature = await signWithHex(privateKeyHex, payload);
|
|
444
|
+
return {
|
|
445
|
+
auth: [{ pubkey: pubkeyHex, signature }],
|
|
446
|
+
payload
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
async function deriveKeyFromSeed(seed, salt, iterations = 1e5) {
|
|
450
|
+
const encoder = new TextEncoder();
|
|
451
|
+
const keyMaterial = await crypto.subtle.importKey(
|
|
452
|
+
"raw",
|
|
453
|
+
encoder.encode(seed),
|
|
454
|
+
"PBKDF2",
|
|
455
|
+
false,
|
|
456
|
+
["deriveBits"]
|
|
457
|
+
);
|
|
458
|
+
const derivedBits = await crypto.subtle.deriveBits(
|
|
459
|
+
{
|
|
460
|
+
name: "PBKDF2",
|
|
461
|
+
salt: encoder.encode(salt),
|
|
462
|
+
iterations,
|
|
463
|
+
hash: "SHA-256"
|
|
464
|
+
},
|
|
465
|
+
keyMaterial,
|
|
466
|
+
256
|
|
467
|
+
);
|
|
468
|
+
return encodeHex(new Uint8Array(derivedBits));
|
|
469
|
+
}
|
|
470
|
+
function generateNonce(length = 12) {
|
|
471
|
+
return crypto.getRandomValues(new Uint8Array(length));
|
|
472
|
+
}
|
|
473
|
+
function generateRandomData(size) {
|
|
474
|
+
return crypto.getRandomValues(new Uint8Array(size));
|
|
475
|
+
}
|
|
476
|
+
async function exportPrivateKeyPem(privateKey, label) {
|
|
477
|
+
const der = new Uint8Array(await crypto.subtle.exportKey("pkcs8", privateKey));
|
|
478
|
+
return toPem(der, label);
|
|
479
|
+
}
|
|
480
|
+
function toPem(der, label) {
|
|
481
|
+
const base64 = encodeBase64(der);
|
|
482
|
+
const formatted = base64.match(/.{1,64}/g)?.join("\n") ?? base64;
|
|
483
|
+
return `-----BEGIN ${label}-----
|
|
484
|
+
${formatted}
|
|
485
|
+
-----END ${label}-----`;
|
|
486
|
+
}
|
|
487
|
+
async function signPayload(params) {
|
|
488
|
+
const { payload, identity } = params;
|
|
489
|
+
const signature = await identity.sign(payload);
|
|
490
|
+
return [{ pubkey: identity.publicKeyHex, signature }];
|
|
491
|
+
}
|
|
492
|
+
async function verifyPayload(params) {
|
|
493
|
+
const { payload, auth } = params;
|
|
494
|
+
const results = await Promise.all(auth.map(async (entry) => {
|
|
495
|
+
const ok = await verify(entry.pubkey, entry.signature, payload);
|
|
496
|
+
return { pubkey: entry.pubkey, ok };
|
|
497
|
+
}));
|
|
498
|
+
const verified = results.every((r) => r.ok);
|
|
499
|
+
const signers = results.filter((r) => r.ok).map((r) => r.pubkey);
|
|
500
|
+
return { verified, signers };
|
|
501
|
+
}
|
|
502
|
+
async function createSignedEncryptedMessage(paramsOrData, signers, recipientPublicKeyHex) {
|
|
503
|
+
if (typeof paramsOrData === "object" && paramsOrData !== null && "encryptionKey" in paramsOrData) {
|
|
504
|
+
const { data, identity, encryptionKey } = paramsOrData;
|
|
505
|
+
const payload = await encryptionKey.encrypt(data);
|
|
506
|
+
const auth2 = await signPayload({ payload, identity });
|
|
507
|
+
return { auth: auth2, payload };
|
|
508
|
+
}
|
|
509
|
+
if (!signers || !recipientPublicKeyHex) {
|
|
510
|
+
throw new Error("Invalid arguments for legacy createSignedEncryptedMessage");
|
|
511
|
+
}
|
|
512
|
+
const encrypted = await encrypt(paramsOrData, recipientPublicKeyHex);
|
|
513
|
+
const auth = await Promise.all(
|
|
514
|
+
signers.map(async (signer) => {
|
|
515
|
+
const signature = await sign(signer.privateKey, encrypted);
|
|
516
|
+
return { pubkey: signer.publicKeyHex, signature };
|
|
517
|
+
})
|
|
518
|
+
);
|
|
519
|
+
return { auth, payload: encrypted };
|
|
520
|
+
}
|
|
521
|
+
async function verifyAndDecryptMessage(params) {
|
|
522
|
+
const { message, encryptionKey } = params;
|
|
523
|
+
const { verified, signers } = await verifyPayload({
|
|
524
|
+
payload: message.payload,
|
|
525
|
+
auth: message.auth
|
|
526
|
+
});
|
|
527
|
+
const data = encryptionKey instanceof SecretEncryptionKey ? await encryptionKey.decrypt(message.payload) : await encryptionKey.decrypt(message.payload);
|
|
528
|
+
return { data, verified, signers };
|
|
529
|
+
}
|
|
530
|
+
async function encryptSymmetric(data, keyHex) {
|
|
531
|
+
const keyBytes = decodeHex(keyHex).buffer;
|
|
532
|
+
const aesKey = await crypto.subtle.importKey(
|
|
533
|
+
"raw",
|
|
534
|
+
keyBytes,
|
|
535
|
+
{ name: "AES-GCM" },
|
|
536
|
+
false,
|
|
537
|
+
["encrypt"]
|
|
538
|
+
);
|
|
539
|
+
const nonce = generateNonce();
|
|
540
|
+
const encoder = new TextEncoder();
|
|
541
|
+
const ciphertext = await crypto.subtle.encrypt(
|
|
542
|
+
{ name: "AES-GCM", iv: nonce },
|
|
543
|
+
aesKey,
|
|
544
|
+
encoder.encode(JSON.stringify(data))
|
|
545
|
+
);
|
|
546
|
+
return {
|
|
547
|
+
data: encodeBase64(new Uint8Array(ciphertext)),
|
|
548
|
+
nonce: encodeBase64(nonce)
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
async function decryptSymmetric(payload, keyHex) {
|
|
552
|
+
const keyBytes = decodeHex(keyHex).buffer;
|
|
553
|
+
const aesKey = await crypto.subtle.importKey(
|
|
554
|
+
"raw",
|
|
555
|
+
keyBytes,
|
|
556
|
+
{ name: "AES-GCM" },
|
|
557
|
+
false,
|
|
558
|
+
["decrypt"]
|
|
559
|
+
);
|
|
560
|
+
const ciphertext = new Uint8Array(decodeBase64(payload.data));
|
|
561
|
+
const nonce = new Uint8Array(decodeBase64(payload.nonce));
|
|
562
|
+
const plaintext = await crypto.subtle.decrypt(
|
|
563
|
+
{ name: "AES-GCM", iv: nonce },
|
|
564
|
+
aesKey,
|
|
565
|
+
ciphertext
|
|
566
|
+
);
|
|
567
|
+
const decoder = new TextDecoder();
|
|
568
|
+
return JSON.parse(decoder.decode(plaintext));
|
|
569
|
+
}
|
|
570
|
+
async function createSignedSymmetricMessage(data, signers, keyHex) {
|
|
571
|
+
const encryptedPayload = await encryptSymmetric(data, keyHex);
|
|
572
|
+
const auth = await Promise.all(
|
|
573
|
+
signers.map(async (signer) => {
|
|
574
|
+
const signature = await sign(signer.privateKey, encryptedPayload);
|
|
575
|
+
return {
|
|
576
|
+
pubkey: signer.publicKeyHex,
|
|
577
|
+
signature
|
|
578
|
+
};
|
|
579
|
+
})
|
|
580
|
+
);
|
|
581
|
+
return {
|
|
582
|
+
auth,
|
|
583
|
+
payload: encryptedPayload
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export {
|
|
588
|
+
IdentityKey,
|
|
589
|
+
PublicEncryptionKey,
|
|
590
|
+
SecretEncryptionKey,
|
|
591
|
+
PrivateEncryptionKey,
|
|
592
|
+
pemToCryptoKey,
|
|
593
|
+
generateSigningKeyPair,
|
|
594
|
+
generateEncryptionKeyPair,
|
|
595
|
+
sign,
|
|
596
|
+
signWithHex,
|
|
597
|
+
verify,
|
|
598
|
+
encrypt,
|
|
599
|
+
decrypt,
|
|
600
|
+
decryptWithHex,
|
|
601
|
+
createAuthenticatedMessage,
|
|
602
|
+
createAuthenticatedMessageWithHex,
|
|
603
|
+
deriveKeyFromSeed,
|
|
604
|
+
generateNonce,
|
|
605
|
+
generateRandomData,
|
|
606
|
+
exportPrivateKeyPem,
|
|
607
|
+
signPayload,
|
|
608
|
+
verifyPayload,
|
|
609
|
+
createSignedEncryptedMessage,
|
|
610
|
+
verifyAndDecryptMessage,
|
|
611
|
+
encryptSymmetric,
|
|
612
|
+
decryptSymmetric,
|
|
613
|
+
createSignedSymmetricMessage,
|
|
614
|
+
mod_exports
|
|
615
|
+
};
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
// clients/http/mod.ts
|
|
2
2
|
var HttpClient = class {
|
|
3
|
-
baseUrl;
|
|
4
|
-
headers;
|
|
5
|
-
timeout;
|
|
6
3
|
constructor(config) {
|
|
7
4
|
this.baseUrl = config.url.replace(/\/$/, "");
|
|
8
5
|
this.headers = config.headers || {};
|
|
@@ -109,19 +106,19 @@ var HttpClient = class {
|
|
|
109
106
|
try {
|
|
110
107
|
const { protocol, domain, path } = this.parseUri(uri);
|
|
111
108
|
const params = new URLSearchParams();
|
|
112
|
-
if (options
|
|
109
|
+
if (options?.page) {
|
|
113
110
|
params.set("page", options.page.toString());
|
|
114
111
|
}
|
|
115
|
-
if (options
|
|
112
|
+
if (options?.limit) {
|
|
116
113
|
params.set("limit", options.limit.toString());
|
|
117
114
|
}
|
|
118
|
-
if (options
|
|
115
|
+
if (options?.pattern) {
|
|
119
116
|
params.set("pattern", options.pattern);
|
|
120
117
|
}
|
|
121
|
-
if (options
|
|
118
|
+
if (options?.sortBy) {
|
|
122
119
|
params.set("sortBy", options.sortBy);
|
|
123
120
|
}
|
|
124
|
-
if (options
|
|
121
|
+
if (options?.sortOrder) {
|
|
125
122
|
params.set("sortOrder", options.sortOrder);
|
|
126
123
|
}
|
|
127
124
|
const queryString = params.toString();
|
|
@@ -135,8 +132,8 @@ var HttpClient = class {
|
|
|
135
132
|
success: true,
|
|
136
133
|
data: [],
|
|
137
134
|
pagination: {
|
|
138
|
-
page:
|
|
139
|
-
limit:
|
|
135
|
+
page: options?.page || 1,
|
|
136
|
+
limit: options?.limit || 50
|
|
140
137
|
}
|
|
141
138
|
};
|
|
142
139
|
}
|
|
@@ -147,8 +144,8 @@ var HttpClient = class {
|
|
|
147
144
|
success: true,
|
|
148
145
|
data: [],
|
|
149
146
|
pagination: {
|
|
150
|
-
page:
|
|
151
|
-
limit:
|
|
147
|
+
page: options?.page || 1,
|
|
148
|
+
limit: options?.limit || 50
|
|
152
149
|
}
|
|
153
150
|
};
|
|
154
151
|
}
|