Number | Name | User | |
---|---|---|---|
99970 | João Maçãs | https://github.com/joaodrmacas | mailto:joaomacas02@tecnico.ulisboa.pt |
103369 | Miguel Parece | https://github.com/BobUser | mailto:miguelparece.ulisboa.pt |
103708 | Duarte Sao Jose | https://github.com/DuarteSJ | duarte.s.jose@tecnico.ulisboa.pt |
This repository contains documentation and source code for the Network and Computer Security (SIRS) project.
The REPORT document provides a detailed overview of the key technical decisions and various components of the implemented project. It offers insights into the rationale behind these choices, the project's architecture, and the impact of these decisions on the overall functionality and performance of the system.
This document presents installation and demonstration instructions.
To see the project in action, it is necessary to setup a virtual environment, with 2 networks and 4 machines.
The following diagram shows the networks and machines:
(include a text-based or an image-based diagram)
Install Vagrant on your system.
- Start the virtual machines:
$ vagrant up
- Check available machines:
$ vagrant status
- Connect to the desired machine:
$ vagrant ssh <machine-name>
For each machine, there is an initialization script inside of the scripts
folder with the machine name (prefix setup_
, suffix .sh
) that installs necessary packages and configures the clean machine.
These scripts are run automatically by executing vagrant up
The Vagrantfile in the repository manages the VM configurations and provisioning.
This machine runs a MongoDB server that provides data storage for the application.
To verify:
$ mongod --version
$ systemctl status mongod
To test:
$ mongosh --tls \
--host 192.168.56.17 \
--tlsCertificateKeyFile /home/vagrant/certs/mongodb/mongodb-server.pem \
--tlsCAFile /home/vagrant/certs/ca.crt
> use secure_document_db
> db.runCommand({ ping: 1 })
The expected results are a successful connection to MongoDB with status code 1.
If you receive the following message "Failed to connect to MongoDB", then:
$ sudo systemctl start mongod
$ sudo systemctl enable mongod
This machine runs a server with a Python socket. It is responsible for handling client requests in a secure manner and ensures network communications with both users and the database.
To verify:
$ python3 -V
To test:
$ cd app
$ python3 server.py
The expected results are the server starting and listening for incoming connections on the 5000 port.
If you receive the message "Address already in use", then:
$ sudo lsof -i :5000
$ sudo kill <process_id>
This machine runs a Text User Interface (TUI) application built in Python that allows users to interact with our application.
To verify:
$ python3 -V # Verify Python installation
To test:
$ cd /home/vagrant/client/notist_client/src
$ python3 main.py
The expected results are a TUI appearing in your terminal where it will tell you that no user was found and ask if you want to create a new account.
If you get a message that looks like ModuleNotFoundError
, then ensure you have all required Python packages installed by reinstalling all the requirements:
$ cd /home/vagrant/client/notist_client
$ pip install -r requirements.txt
Now that all the networks and machines are up and running, the following section will show how to use the client and how the requests are being sent between components.
If you followed the instructions above, your client should be displaying the following message.
No user found. Proceeding with registration.
ATTENTION- This will overwrite any existing user data.
Would you like to continue? [yes/no]
> yes
Enter your username (must be unique):
Enter your password:
Make sure to answer yes to the first prompt and then proceed to create the user. At this point, the main menu of the application should appear:
=== NoteIST ===
1. Create a Note
2. Show Notes List
3. View Note Content
4. Edit a Note
5. Delete a Note
6. Add contributor to a note
7. Remove contributor from a note
8. Push changes to remote server
9: Pull changes from remote server
10. Exit
Choose an option:
These are the functionalities of our program. After registering, all of them except the push and pull from server will be available without internet connection.
To create a note simply press 1 and you will be prompted with the following:
Choose an option: 1
Enter note title: ola
Enter note content: ola
Locally a directory is createdd on ~/.local/share/NoteIST/notes <note_id> with a key and the following file:
{
"id": "04a34e14-2f3d-4d8b-b631-a30b0712f048",
"title": "78882c834cd90b65516caa4cd16ef1ec",
"note": "4037afed5bec821498ee59ffe1c10e4b",
"owner": {
"username": "joao"
},
"version": 1,
"editors": [],
"viewers": [],
"iv": "33f5c845e79510b1016860e5cea4cc43",
"hmac": "11eb278f3cae1ba4bc7ffffd6d0a72d27409d53bc35d65761a04c1f0592f7efd"
}
As we can see the sensitive information is censored and completely unreadable. The key file in the folder alongside this note is NOT the key to unencrypt it, but an encrypted version of said key with the master key derivated from your password.
To add a collaborator to your note, you will need to know the collaborator username beforehand. When you have this information press 6 on the main menu:
Choose an option: 6
Available notes:
1: ola (v1)
Select a note by number: 1
Enter the username of the contributor: miguel
Would you like to give miguel editing permissions to this note, joao? [yes/no]y
This adds miguel as a editor to your note, however for him to receive the note, we have to push this changes to the server.
Still using the main menu, we will press 8 to send every change to the server. A report of all the changes will be printed for you to know what was successful.
Server response: success - Actions processed
{'action': 'create_note', 'status': 'success', 'result': {'status': 'success', 'message': 'Note 04a34e14-2f3d-4d8b-b631-a30b0712f048 created'}}
{'collab': 'add_collaborator', 'status': 'success', 'result': {'status': 'success', 'message': 'Collaborator miguel added to note 04a34e14-2f3d-4d8b-b631-a30b0712f048'}}
As we can see, the note creation and adding miguel as a collaborator worked. This means the notes secret key was also encrypted with miguel's public key and sent to the server, which then added it to miguel's representation in the db so that he can receive it when the server sends him the note (this will happens when miguel executes a pul command). When the server receives a note, it will add some metadata to it and send it to the database for it to be stored securely.
Here we can see an example of the data sent through the client socket.
Now we will compare the data sent before entering the socket and the data caught with wireshark. consider these bytes from a push request with a note creation action.
Consider the stream caught on the Wireshark:
We can identify 5-byte headers that indicate TLS record starts. First byte represents the Record type, second and third bytes represent the TLS version, and the fourth and fifth bytes represent the length of the record. In this Stream we can identify 17 03 03 04 ab Header that means that the record is a TLS 1.3 record with 1195 bytes of length. This is the record that pr contains the message sent by the client to the server. The data following the header is the data sent(encrypted).
Now switching to the miguel POV we can see that by pressing 9 followed by a 3 and then a 1 on the main menu we get this:
Select an option: 9
Server response: success - Documents retrieved successfully
...
Select an option: 3
Available notes:
1: ola (v1)
Select a note by number: 1
Title: ola
Content: ola
We can see that Miguel received the note that was encrypted initially without the server or db ever getting access to the sensitive content. This is how the note is represented in the database:
{
_id: ObjectId('67770560239543ab8405e278'),
id: '04a34e14-2f3d-4d8b-b631-a30b0712f048',
iv: '33f5c845e79510b1016860e5cea4cc43',
hmac: '11eb278f3cae1ba4bc7ffffd6d0a72d27409d53bc35d65761a04c1f0592f7efd',
title: '78882c834cd90b65516caa4cd16ef1ec',
note: '4037afed5bec821498ee59ffe1c10e4b',
date_created: ISODate('2025-01-02T21:30:08.098Z'),
date_modified: ISODate('2025-01-02T21:30:08.098Z'),
last_modified_by: 'a21b1134-62e9-4533-8ac8-152f69fa7a07',
version: 1,
owner: { id: 'a21b1134-62e9-4533-8ac8-152f69fa7a07', username: 'joao' },
editors: [
{
id: '48ad0cc5-1eb4-42af-9b19-217b0dd3dfdd',
username: 'miguel'
},
],
viewers: [
{
id: '48ad0cc5-1eb4-42af-9b19-217b0dd3dfdd',
username: 'miguel'
},
]
}
If someone get's access to your computer and changes the content of a note the following will appear when you try to read it
An unexpected error occured: Failed to read and decrypt file: Decryption failed. It is likely that your file has been tampered with. Details: non-hexadecimal number found in fromhex() arg at position 33
or
An unexpected error occured: Failed to read and decrypt file: Decryption failed. It is likely that your file has been tampered with. Details: Padding is incorrect.
If someone tries to resend a request you have sent in the past, the server will identify that the request was performed by an attacker by using the timestamp. Below we can see a picture of the server receiving 2 exact same requests and identifying that one is stale.
If someone catches your request on the network and tries to change any of the data on it, the signature check will fail on the server side and the server will reply with:
{"status": "error", "message": "Signature verification failed"}
vOk. Now that we kersionsnow there is no way for anyone to change your notes lets see what happens if someone deletes one of your notes locally. Here, two things may happen. If you hadn't pushed your changes to the remte server you will permanently loose access to the note, but if your changes were pushed here is what happens:
The user list his notes and sees everything is ok:
o
Someone gains access to the local file system and deletes the last version of the note:
Later, the user lists his notes and sees the last version is missing:
He can just pull from the server and get the note again:
-
pip (≥23.0.0)
- Documentation: pip docs
- Repository: pypa/pip
- Package Index: pip on PyPI
-
setuptools (≥65.5.1)
- Documentation: setuptools docs
- Repository: pypa/setuptools
- Package Index: setuptools on PyPI
-
wheel (≥0.40.0)
- Documentation: wheel docs
- Repository: pypa/wheel
- Package Index: wheel on PyPI
-
cryptography (==3.4.7)
- Documentation: cryptography docs
- Repository: pyca/cryptography
- Package Index: cryptography on PyPI
-
pycryptodome (==3.21.0)
- Documentation: pycryptodome docs
- Repository: Legrandin/pycryptodome
- Package Index: pycryptodome on PyPI
-
pydantic (==2.10.4)
- Documentation: pydantic docs
- Repository: pydantic/pydantic
- Package Index: pydantic on PyPI
-
importlib_metadata (≥4.13.0)
- Documentation: importlib_metadata docs
- Repository: python/importlib_metadata
- Package Index: importlib_metadata on PyPI
- vagrant
- Documentation: vagrant docs
- Repository: hashicorp/vagrant
- Download: vagrant downloads
This project is licensed under the MIT License - see the LICENSE.txt for details.