aboutsummaryrefslogtreecommitdiff
path: root/client-web/source/protocol
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-09-09 11:42:06 +0200
committermetamuffin <metamuffin@disroot.org>2022-09-09 11:42:06 +0200
commitb6d93e0f322901dfc1fee23f3d396a68e61e1b29 (patch)
tree01ba855cf41fb53f84cd6eb504c4f4ba0134fdfa /client-web/source/protocol
parentafed94bb4609bd796102c9184f13fa29c5f92a48 (diff)
downloadkeks-meet-b6d93e0f322901dfc1fee23f3d396a68e61e1b29.tar
keks-meet-b6d93e0f322901dfc1fee23f3d396a68e61e1b29.tar.bz2
keks-meet-b6d93e0f322901dfc1fee23f3d396a68e61e1b29.tar.zst
crypto stuff
Diffstat (limited to 'client-web/source/protocol')
-rw-r--r--client-web/source/protocol/crypto.ts80
-rw-r--r--client-web/source/protocol/mod.ts15
2 files changed, 93 insertions, 2 deletions
diff --git a/client-web/source/protocol/crypto.ts b/client-web/source/protocol/crypto.ts
new file mode 100644
index 0000000..6cd2ba3
--- /dev/null
+++ b/client-web/source/protocol/crypto.ts
@@ -0,0 +1,80 @@
+import { log } from "../logger.ts";
+
+//! I am not a crypto expert at all! Please read carefully and report any issues to me.
+
+export async function crypto_seeded_key(seed: string): Promise<CryptoKey> {
+ log("crypto", "importing seed…")
+ const seed_key = await window.crypto.subtle.importKey(
+ "raw",
+ new TextEncoder().encode(seed),
+ "PBKDF2",
+ false,
+ ["deriveKey"]
+ )
+ //? TODO is it possible to use a unique seed per session here?
+ // const salt = window.crypto.getRandomValues(new Uint8Array(16));
+ const salt = base64_to_buf("thisisagoodsaltAAAAAAA==") // valid "unique" 16-byte base-64 string
+ log("crypto", "deriving key…")
+ const key = await window.crypto.subtle.deriveKey(
+ {
+ name: "PBKDF2",
+ salt,
+ iterations: 250000,
+ hash: "SHA-256",
+ },
+ seed_key,
+ { name: "AES-GCM", length: 256 },
+ false,
+ ["encrypt", "decrypt"]
+ )
+ console.log(key);
+ log("crypto", "ready")
+ return key
+}
+
+export async function crypto_encrypt(key: CryptoKey, data: string): Promise<string> {
+ const iv = window.crypto.getRandomValues(new Uint8Array(12));
+ const ciphertext = new Uint8Array(await window.crypto.subtle.encrypt(
+ { name: "AES-GCM", iv },
+ key,
+ new TextEncoder().encode(data)
+ ));
+ const buf = new Uint8Array(iv.byteLength + ciphertext.byteLength);
+ buf.set(iv, 0);
+ buf.set(ciphertext, iv.byteLength);
+ const b64 = buf_to_base64(buf);
+ return b64;
+}
+
+export async function crypt_decrypt(key: CryptoKey, data: string): Promise<string> {
+ const buf = base64_to_buf(data);
+ const iv = buf.slice(0, 12);
+ const ciphertext = buf.slice(12);
+ const decryptedContent = await window.crypto.subtle.decrypt(
+ { name: "AES-GCM", iv },
+ key,
+ ciphertext
+ );
+ const plain = new TextDecoder().decode(decryptedContent);
+ return plain
+}
+
+// const buf_to_base64 = (buf: Uint8Array) => btoa(String.fromCharCode.apply(null, buf));
+// const base64_to_buf = (b64: string) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
+
+export function base64_to_buf(data: string): Uint8Array {
+ const binary_string = globalThis.atob(data);
+ const bytes = new Uint8Array(binary_string.length);
+ for (let i = 0; i < binary_string.length; i++) {
+ bytes[i] = binary_string.charCodeAt(i);
+ }
+ return bytes;
+}
+
+export function buf_to_base64(bytes: Uint8Array): string {
+ let binary = '';
+ for (let i = 0; i < bytes.byteLength; i++) {
+ binary += String.fromCharCode(bytes[i]);
+ }
+ return globalThis.btoa(binary);
+} \ No newline at end of file
diff --git a/client-web/source/protocol/mod.ts b/client-web/source/protocol/mod.ts
index 76b1290..f86e96f 100644
--- a/client-web/source/protocol/mod.ts
+++ b/client-web/source/protocol/mod.ts
@@ -1,6 +1,17 @@
+import { crypto_seeded_key } from "./crypto.ts"
export class SignalingConnection {
- constructor(room: string) {
-
+ room!: string
+ websocket!: WebSocket
+ signaling_id!: string
+ key!: CryptoKey
+
+ constructor() { }
+ async connect(room: string): Promise<SignalingConnection> {
+ this.key = await crypto_seeded_key(room)
+ const ws_url = new URL(`${window.location.protocol.endsWith("s:") ? "wss" : "ws"}://${window.location.host}/signaling/${encodeURIComponent(this.signaling_id)}`)
+ this.websocket = new WebSocket(ws_url)
+ await new Promise(r => this.websocket!.onopen = r)
+ return this
}
}