|
@@ -86,6 +86,21 @@ const code = `
|
86
|
86
|
this._id = id;
|
87
|
87
|
}
|
88
|
88
|
|
|
89
|
+ /**
|
|
90
|
+ * Derives a per-participant key.
|
|
91
|
+ * @param {Uint8Array} keyBytes - Value to derive key from
|
|
92
|
+ * @param {Uint8Array} salt - Salt used in key derivation
|
|
93
|
+ */
|
|
94
|
+ async deriveKey(keyBytes, salt) {
|
|
95
|
+ const encoder = new TextEncoder();
|
|
96
|
+ const idBytes = encoder.encode(this._id);
|
|
97
|
+ // Separate both parts by a null byte to avoid ambiguity attacks.
|
|
98
|
+ const participantSalt = new Uint8Array(salt.byteLength + idBytes.byteLength + 1);
|
|
99
|
+ participantSalt.set(salt);
|
|
100
|
+ participantSalt.set(idBytes, salt.byteLength + 1);
|
|
101
|
+
|
|
102
|
+ return deriveKey(keyBytes, participantSalt);
|
|
103
|
+ }
|
89
|
104
|
/**
|
90
|
105
|
* Sets a key and starts using it for encrypting.
|
91
|
106
|
* @param {CryptoKey} key
|
|
@@ -304,7 +319,7 @@ const code = `
|
304
|
319
|
.pipeThrough(transformStream)
|
305
|
320
|
.pipeTo(writableStream);
|
306
|
321
|
if (keyBytes) {
|
307
|
|
- context.setKey(await deriveKey(keyBytes, keySalt));
|
|
322
|
+ context.setKey(await context.deriveKey(keyBytes, keySalt));
|
308
|
323
|
}
|
309
|
324
|
} else if (operation === 'decode') {
|
310
|
325
|
const { readableStream, writableStream, participantId } = event.data;
|
|
@@ -321,13 +336,13 @@ const code = `
|
321
|
336
|
.pipeThrough(transformStream)
|
322
|
337
|
.pipeTo(writableStream);
|
323
|
338
|
if (keyBytes) {
|
324
|
|
- context.setKey(await deriveKey(keyBytes, keySalt));
|
|
339
|
+ context.setKey(await context.deriveKey(keyBytes, keySalt));
|
325
|
340
|
}
|
326
|
341
|
} else if (operation === 'setKey') {
|
327
|
342
|
keyBytes = event.data.key;
|
328
|
343
|
contexts.forEach(async context => {
|
329
|
344
|
if (keyBytes) {
|
330
|
|
- context.setKey(await deriveKey(keyBytes, keySalt));
|
|
345
|
+ context.setKey(await context.deriveKey(keyBytes, keySalt));
|
331
|
346
|
} else {
|
332
|
347
|
context.setKey(false);
|
333
|
348
|
}
|