From 4827e6ae57d4cc8da052e5497406ac1d443ce334 Mon Sep 17 00:00:00 2001 From: Sam Hadow Date: Sun, 9 Feb 2025 17:38:42 +0100 Subject: [PATCH] init db + ecc tests + register popup (non functionnal) --- Makefile | 2 +- src/app.js | 4 ++ src/controllers/main.js | 3 ++ src/db.js | 91 ++++++++++++++++++++++++++++++--------- src/public/ecc.js | 95 +++++++++++++++++++++++++++++++++++++++++ src/public/index.html | 16 +++++++ src/public/popups.js | 17 ++++++++ src/public/style.css | 26 +++++++++++ src/routes/root.js | 4 ++ 9 files changed, 238 insertions(+), 20 deletions(-) create mode 100644 src/public/popups.js diff --git a/Makefile b/Makefile index e3b8cd1..45089a7 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ run: clean build podman pod create --name=e2ee -p 3333:3333 podman run -d --pod=e2ee -e POSTGRES_PASSWORD="password" -e POSTGRES_DB="e2ee" -e POSTGRES_USER="e2ee" -e POSTGRES_INITDB_ARGS="--encoding=UTF-8 --lc-collate=C --lc-ctype=C" --name=e2ee-db docker.io/library/postgres:15 - podman run -d --pod=e2ee --name=e2ee-app e2ee-messaging-service:latest + podman run -d --pod=e2ee -e POSTGRES_PASSWORD="password" -e POSTGRES_DB="e2ee" -e POSTGRES_USER="e2ee" --name=e2ee-app e2ee-messaging-service:latest build: podman build -t e2ee-messaging-service . test: diff --git a/src/app.js b/src/app.js index 65061a3..a97ddf2 100644 --- a/src/app.js +++ b/src/app.js @@ -10,6 +10,10 @@ app.use(cookieParser()); // bootstrap app.use('/css', express.static(__dirname + '/node_modules/bootstrap/dist/css')); +//database +const database = require(__dirname + '/db'); +database.init(); + //routes const routes = require(__dirname + '/routes'); app.use("/", routes); diff --git a/src/controllers/main.js b/src/controllers/main.js index db3db58..010aed9 100644 --- a/src/controllers/main.js +++ b/src/controllers/main.js @@ -12,6 +12,9 @@ const mainController = { }, ecc: (req, res) => { res.sendFile(path.resolve(__dirname + '/../public/ecc.js')); + }, + popups: (req, res) => { + res.sendFile(path.resolve(__dirname + '/../public/popups.js')); } }; diff --git a/src/db.js b/src/db.js index 9e5e654..5003a89 100644 --- a/src/db.js +++ b/src/db.js @@ -1,4 +1,4 @@ -const { Client } = require('pg'); +const { Pool } = require('pg'); const dbConfig = { user: process.env.POSTGRES_USER || 'e2ee', @@ -8,29 +8,82 @@ const dbConfig = { database: process.env.POSTGRES_DB || 'e2ee', }; -const client = new Client(dbConfig); +const pool = new Pool(dbConfig); const database = { - init: () => { - client.connect().then(() => { - let querryString = ` - CREATE table user ( - uuid integer primary key, - pubkey text - ); - ` - client.query(querryString, (err, _) => { - if (err) { - console.error('Error executing query', err); + init: async () => { + while (true) { + try { + await database.checkIfDatabaseIsUp(); + console.log('Database is up, initializing...'); + database.checkSchema().then((exists) => { + if (!exists) { + database.createTables(); + } else { + console.log("Database schema is already correct."); + } + }).catch((err) => { + console.error("Error checking schema:", err); + }); + break; + } catch (err) { + console.error('Waiting for the database to start...'); } - client.end().then(() => {}).catch((err) => { - console.error('Error closing connection', err); + await new Promise(resolve => setTimeout(resolve, 5000)); + } + }, + createTables: () => { + pool.query(` + CREATE TABLE IF NOT EXISTS "user" ( + uuid integer PRIMARY KEY, + pubkey text + ); + `, (err, _) => { + if (err) { + console.error('Error creating user table', err); + return; + } + pool.query(` + CREATE SEQUENCE IF NOT EXISTS uuid_sequence + INCREMENT BY 1 + START WITH 1; + `, (err, _) => { + if (err) { + console.error('Error creating sequence', err); + } else { + console.log("user table and sequence created successfully."); + } }); }); - }).catch((err) => { - console.error('Error connecting to database ', err); - }); - } + }, + checkSchema: () => { + return new Promise((resolve, reject) => { + pool.query(` + SELECT EXISTS ( + SELECT 1 FROM pg_tables WHERE tablename = 'user' + ) AS table_exists; + `, (err, res) => { + if (err) { + console.error('Error executing query', err); + reject(err); + } else { + const tableExists = res.rows[0].table_exists; + resolve(tableExists); + } + }); + }); + }, + checkIfDatabaseIsUp: () => { + return new Promise((resolve, reject) => { + pool.query('SELECT 1', (err, res) => { + if (err) { + reject(false); + } else { + resolve(true); + } + }); + }); + } }; module.exports = database; diff --git a/src/public/ecc.js b/src/public/ecc.js index e69de29..ea359b2 100644 --- a/src/public/ecc.js +++ b/src/public/ecc.js @@ -0,0 +1,95 @@ +/* +Convert an ArrayBuffer into a string +from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String +*/ +function ab2str(buf) { + return String.fromCharCode.apply(null, new Uint8Array(buf)); +} + +function exportedKeyToPem(key, type) { + let exportedAsString = ab2str(key); + let exportedAsBase64 = window.btoa(exportedAsString); + return `-----BEGIN ${type.toUpperCase()} KEY-----\n${exportedAsBase64}\n-----END ${type.toUpperCase()} KEY-----`; +} + +async function genKey() { + // Generate keys + const { publicKey, privateKey } = await crypto.subtle.generateKey( + // { + // name: "ECDSA", + // namedCurve: "P-384", + // }, + { + name: "Ed25519", + }, + true, + ["sign", "verify"], + ); + const exportedPubkey = await crypto.subtle.exportKey("spki", publicKey); + const exportedPrivkey = await crypto.subtle.exportKey("pkcs8", privateKey); + // const privkey = await crypto.subtle.wrapKey("pkcs8", privateKey, wrapkey, { name: "AES-KW" }); + + console.log(`publicKey: ${exportedKeyToPem(exportedPubkey, publicKey.type)}`); + console.log(`privateKey: ${exportedKeyToPem(exportedPrivkey, privateKey.type)}`); +} + +async function test(data) { + console.log(`Message: ${data}`); + try { + // Generate keys + const { publicKey, privateKey } = await crypto.subtle.generateKey( + { + name: "Ed25519", + }, + true, + ["sign", "verify"], + ); + + console.log(`publicKey: ${publicKey}, type: ${publicKey.type}`); + console.log(`privateKey: ${privateKey}, type: ${privateKey.type}`); + + // Encode data prior to signing + const encoder = new TextEncoder(); + encodedData = encoder.encode(data); + + // Log the first part of the encoded data + const shorterEncodedBuffer = new Uint8Array(encodedData.buffer, 0, 14); + console.log( + `encodedData: ${shorterEncodedBuffer}...[${encodedData.byteLength} bytes total]`, + ); + //console.log(`encodedData: ${encodedData}`); + + // Sign the data using the private key. + const signature = await crypto.subtle.sign( + { + name: "Ed25519", + }, + privateKey, + encodedData, + ); + + // Log the first part of the signature data + const signatureBuffer = new Uint8Array(signature, 0, 14); + console.log( + `signature: ${signatureBuffer}...[${signature.byteLength} bytes total]`, + ); + + // Verify the signature using the public key + const verifyResult = await crypto.subtle.verify( + { + name: "Ed25519", + }, + publicKey, + signature, + encodedData, + ); + + // Log result - true if the text was signed with the corresponding public key. + console.log(`signature verified?: ${verifyResult}`); + } catch (error) { + console.log(error); + } +} + +test('ceci est un test'); +genKey() diff --git a/src/public/index.html b/src/public/index.html index 76009c0..bd5ae5e 100644 --- a/src/public/index.html +++ b/src/public/index.html @@ -8,12 +8,28 @@ +
Please enable Javascript to use this app.
+ + Get cookie
diff --git a/src/public/popups.js b/src/public/popups.js new file mode 100644 index 0000000..614fa27 --- /dev/null +++ b/src/public/popups.js @@ -0,0 +1,17 @@ +// close popups with escape key +document.addEventListener("keydown", (event) => { + if (event.isComposing || event.key === 'Escape') { + Array.from(document.getElementsByClassName("popup")).forEach(function(x) { + x.style.display = 'none'; + }); + } +}); + +// register popup +document.getElementById("register").addEventListener("click", function () { + registerPopup.style.display = 'flex'; +}); +// cancel +document.getElementById("registercancel").addEventListener("click", function () { + registerPopup.style.display = 'none'; +}); diff --git a/src/public/style.css b/src/public/style.css index e69de29..1377136 100644 --- a/src/public/style.css +++ b/src/public/style.css @@ -0,0 +1,26 @@ +body { + margin: 0; + padding: 0; +/* font-family: 'overpass'; */ +} + +.popup { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + justify-content: center; + align-items: center; +} + +.popup-content { + background: #3d3d3d; + padding: 20px; + border-radius: 8px; + text-align: center; + max-height: 70%; + max-width: 60%; +} diff --git a/src/routes/root.js b/src/routes/root.js index a6d9068..3e754da 100644 --- a/src/routes/root.js +++ b/src/routes/root.js @@ -18,4 +18,8 @@ router .route("/ecc.js") .get(mainController.ecc); +router + .route("/popups.js") + .get(mainController.popups); + module.exports = router;