init db + ecc tests + register popup (non functionnal)
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								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: | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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')); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|   | ||||
							
								
								
									
										91
									
								
								src/db.js
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								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; | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										17
									
								
								src/public/popups.js
									
									
									
									
									
										Normal 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'; | ||||
| }); | ||||
| @@ -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%; | ||||
| } | ||||
|   | ||||
| @@ -18,4 +18,8 @@ router | ||||
|   .route("/ecc.js") | ||||
|   .get(mainController.ecc); | ||||
|  | ||||
| router | ||||
|   .route("/popups.js") | ||||
|   .get(mainController.popups); | ||||
|  | ||||
| module.exports = router; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user