document commands

This commit is contained in:
JoaoBastos023 2024-12-30 13:53:11 +00:00
parent 3515497ffd
commit af1f2ecef6
1 changed files with 116 additions and 0 deletions

View File

@ -229,6 +229,7 @@ For the client, each command is executed via terminal and it is used multiple to
* `logging` footnote:[https://docs.python.org/3/library/logging.html] → Logging system to send out messages such as errors. * `logging` footnote:[https://docs.python.org/3/library/logging.html] → Logging system to send out messages such as errors.
* `os` footnote:[https://docs.python.org/3/library/os.html] → Add path to local folder `~/.sio` to save or load any files used by the current command. * `os` footnote:[https://docs.python.org/3/library/os.html] → Add path to local folder `~/.sio` to save or load any files used by the current command.
* `requests` footnote:[https://requests.readthedocs.io/en/latest/] → Main library to allow communication from the client to the API. * `requests` footnote:[https://requests.readthedocs.io/en/latest/] → Main library to allow communication from the client to the API.
* `JSON` footnote:[https://docs.python.org/3/library/json.html] → Main library to store and exchange data between the client and API.
For every command the argument `-r` is present to set the API's address. It is needed to define if it wasn't previously, otherwise an error is cast with the corresponding message. For every command the argument `-r` is present to set the API's address. It is needed to define if it wasn't previously, otherwise an error is cast with the corresponding message.
@ -386,4 +387,119 @@ The username is parsed in the URL, and the session token is, as usual, sent in t
==== Activating a subject ==== Activating a subject
The following command `rep_activate_subject` has a similar implementation as the `rep_suspend_subject` command. The key difference is that instead of activating a subject, it suspends a subject. In order to activate a subject, the subject must be in a suspended state. The following command `rep_activate_subject` has a similar implementation as the `rep_suspend_subject` command. The key difference is that instead of activating a subject, it suspends a subject. In order to activate a subject, the subject must be in a suspended state.
==== Adding a document
Using the command `rep_add_doc` allows the user to upload a document to the current organization his in. The file given is encrypted with symmetric encryption and the key, the document's name and the algorith used is upload as it's metadata to the server.
[source, python]
----
#Encrypt content
key, content = encrypt_file(BASE_DIR + args.file, BASE_DIR + 'encryptedText')
metadata = {'document_name' : args.name, 'key' : key.hex(), 'alg' : 'AES-CFB' }
----
Of course, the information is then encrypted with the derived key located in the session file before sending to the server with a `POST` request.
[source, python]
----
# Encrypting metadata
derived_key = bytes.fromhex(args.session['derived_key'])
metadata = encrypt(metadata, derived_key).hex()
headers = {
'Authorization': args.session['token'],
'Content-Type': 'application/octet-stream'
}
req = requests.post(f'http://{state['REP_ADDRESS']}/file/upload/metadata',
data=metadata,
headers=headers)
----
If the upload is successful, the client proceeds to upload the encrypted content, along with an hash of the content for the server to check for integrity.
[source, python]
----
#Upload Document content
file = {'file' : (BASE_DIR + args.file, content)}
req = requests.post(f'http://{state['REP_ADDRESS']}/file/upload/content',
files=file,
headers={'Authorization': args.session['token'],
'File-Checksum' : digest.get_hash(content)})
----
==== Modifying Access Control List(ACL) from a document
In order to modify the ACL of an organization, the user must have the permission `DOC_ACL`. Once that permission is present, the command `rep_acl_doc` can be used to change specific role's permissions such as
* `DOC_ACL` → Allows the person holding the given role to change the ACL.
* `DOC_READ` → Allows the person holding the given role to read the document.
* `DOC_DELETE` → Allows the person holding the given role to delete the *file_handle*.
==== Getting a document's metadata
Every document has it's metadata that includes the `file handle` and `key`. To get the metadata of a specific document, the command `rep_get_doc_metadata` sends a `GET` request and with the derived key the response is decrypted. Using the `file handle` we can then get the file.
==== Getting a file's content
This command (`rep_get_file`) is relatively simple, the client provides the file handle to the server and it is given the file's content which is either written on the screen or saved in a file given by the user.
==== Decrypting a file
Given the document's metadata and the file's content, what's left to do is to get the actual content by decrypting it. As such, using the command `rep_decrypt_file` the file's content is decrypted using the key given in it's metadata
[source, python]
----
content = symmetric_encryption.decrypt_file(bytes.fromhex(metadata['key']), BASE_DIR + args.encrypted)
----
==== Getting a document's file
The command `rep_get_doc_file` is essentially the union of the last three commands. The document's name given by the user is hashed and a `GET` request is sent to the server to acquire the metadata.
[source, python]
----
doc_name = digest.get_hash(bytes(args.name, encoding='utf-8'))
metadata = requests.get(f'http://{state['REP_ADDRESS']}/file/get/' + doc_name + '/metadata', headers={'Authorization': args.session['token']})
----
The metadata is then decrypted and we get the `file handle` needed to get it's content by sending another `GET` request. If successful, the hash of the file's content must be equal to the file handle, this way we see if the file's integrity is maintained.
[source, python]
----
file = requests.get(f'http://{state['REP_ADDRESS']}/file/get/' + metadata['file_handle'] + '/content')
file = file.content
if not digest.get_hash(file) == metadata['file_handle']:
logger.error("File's integrity was lost.")
sys.exit(-1)
----
Once having both the metadata and the file's content, the client decrypts it like it's being done in the command `rep_decrypt_file`. The file's content is written to a temporary file and it's used symmetric decryption to get the plaintext using the key stored in the metadata.
[source, python]
----
with open(BASE_DIR + 'encrypted_file', 'wb') as f:
f.write(file)
content = symmetric_encryption.decrypt_file(bytes.fromhex(metadata['key']), BASE_DIR + 'encrypted_file')
os.remove(BASE_DIR + 'encrypted_file')
----
==== Listing documents
The command `rep_list_docs` allows the user to get a list of all documents in the organization. To make it organized, the command can be executed with a date and specify if the documents must be older, newer or created in that specific date or it can be filtered by who created the document.
The payload simply contains nothing if there's no subject or date given, or it contains the username, date or both.
[source, python]
----
# Document created after 20/12/2024
payload['datetime'] = {'value' : 20/12/2024, 'relation' : 'nt'}
payload = json.dumps(payload)
payload = encrypt(payload, derived_key).hex()
headers = {
'Authorization': args.session['token'],
'Content-Type': 'application/octet-stream'
}
req = requests.get(f'http://{state['REP_ADDRESS']}/file/list', data=payload, headers=headers)
----