init db + ecc tests + register popup (non functionnal)

This commit is contained in:
Sam Hadow 2025-02-09 17:38:42 +01:00
parent 4abe5a07f2
commit 4827e6ae57
9 changed files with 238 additions and 20 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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'));
}
};

View File

@ -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;

View File

@ -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()

View File

@ -8,12 +8,28 @@
<script src="/socket.io/socket.io.js" defer></script>
<script src="/script.js" defer></script>
<script src="/ecc.js" defer></script>
<script src="/popups.js" defer></script>
<!--load bootstrap-->
<link rel="stylesheet" href="/css/bootstrap.min.css" />
</head>
<body>
<div id="mainbody">
<div id="jswarn"> Please enable Javascript to use this app. </div>
<div class="btn-toolbar btn-group-sm" role="toolbar" aria-label="Toolbar">
<div class="btn-group mr-2" role="group" aria-label="register">
<button id="register" class="btn btn-secondary" type="button">register</button>
</div>
</div>
<div id="registerPopup" class="popup">
<div class="popup-content">
<div class="btn-group mr-2 w-100" role="group" aria-label="Add group">
<input id="sharedsecret" type="text" class="form-control input-sm w-50" placeholder="shared secret" required>
<input id="publickey" type="text" class="form-control input-sm w-50" placeholder="public key">
<button id="registerconfirm" class="btn btn-secondary" type="button">register</button>
<button id="registercancel" class="btn btn-secondary" type="button">cancel</button>
</div>
</div>
</div>
<a href="./account/cookie" class="btn btn-primary">Get cookie</a>
<ul id="messages"></ul>
<form id="form" action="">

17
src/public/popups.js Normal file
View File

@ -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';
});

View File

@ -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%;
}

View File

@ -18,4 +18,8 @@ router
.route("/ecc.js")
.get(mainController.ecc);
router
.route("/popups.js")
.get(mainController.popups);
module.exports = router;