Skip to content
This repository has been archived by the owner on May 31, 2024. It is now read-only.

Commit

Permalink
Update image selector window and server storage
Browse files Browse the repository at this point in the history
manager - firmas
  • Loading branch information
Ragarr committed Nov 9, 2023
1 parent 8ff2675 commit 6778eec
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 57 deletions.
44 changes: 34 additions & 10 deletions src/packages/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
from packages.imgproc import *
from PIL import Image
from packages.imgproc.img_cripto_utils import ImageCryptoUtils
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization


class Client:
def __init__(self):
self.username = None
self.password = None
self.encryptor = None
self.__server = Server()
self._server = Server()
self.__private_key = None
self._public_key = None

def get_images(self, num: int | None = -1, username: str | None = None,
date: str | None = None, time: str | None = None) -> list:
Expand Down Expand Up @@ -39,15 +43,15 @@ def get_images(self, num: int | None = -1, username: str | None = None,
raise Exception("Date must be specified if time is specified")

if username is None:
images = self.__server.get_images(num=num, username=username, date=date, time=time)
images = self._server.get_images(num=num, username=username, date=date, time=time)
progress = 0
for i in images:
yield round((progress / len(images)) * 100, 2), i
progress += 1
return

# if the user is logged in, we will return de decrypted images
images = self.__server.get_images(num=num, username=username, date=date, time=time)
images = self._server.get_images(num=num, username=username, date=date, time=time)
decrypted_images = []
progress = 0
for im in images:
Expand All @@ -66,7 +70,7 @@ def register(self, name: str, password: str) -> None:
password (str): password of the user
"""

return self.__server.create_user(name, password)
return self._server.create_user(name, password)

def logout(self):
"""
Expand All @@ -85,17 +89,23 @@ def login(self, name: str, password: str):
bool: True if the user was logged in, False otherwise
"""

if self.__server.login(name, password):
if self._server.login(name, password):
self.username = name
self.password = password
self.__private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096,
)
self._public_key = self.__private_key.public_key()


else:
raise ValueError("User or password incorrect")

def remove_user(self) -> None:
"""Removes the user from the server"""
if self.__server.login(self.username, self.password):
self.__server.remove_user(self.username, self.password)
if self._server.login(self.username, self.password):
self._server.remove_user(self.username, self.password)

def upload_photo(self, path: str, x: int = 0, y: int = 0, w: int = 200, h: int = 200) -> None:
"""Uploads a photo to the server
Expand All @@ -119,14 +129,28 @@ def upload_photo(self, path: str, x: int = 0, y: int = 0, w: int = 200, h: int =

# encrypt image
image = ImageCryptoUtils.encrypt(image, self.password, x, y, w, h)
ImageCryptoUtils.generate_image_hash(image)
img_hash = ImageCryptoUtils.generate_image_hash(image)
# firmar hash
signature = self.__private_key.sign(
img_hash,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
pem = self._public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
ImageCryptoUtils._write_metadata(image, {"signature":signature.hex(), "public_key": pem.hex()} )
# upload image
return self.__server.store_image(image, self.username, self.password)
return self._server.store_image(image, self.username, self.password)

def remove_image(self, date: str, time: str) -> None:
"""Removes the image with the given name
Args:
date (str): date of the image
time (str): time of the image
"""
return self.__server.remove_image(self.username, self.password, date, time)
return self._server.remove_image(self.username, self.password, date, time)
38 changes: 19 additions & 19 deletions src/packages/imgproc/img_cripto_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ def decrypt(img: Image, password: str) -> Image:

# get the iv from the image metadata
metadata = ImageCryptoUtils.__read_metadata(img)
iv = bytes.fromhex(metadata["iv"])
salt = bytes.fromhex(metadata["salt"])
x = int(metadata["x"])
y = int(metadata["y"])
width = int(metadata["width"])
height = int(metadata["height"])
iv = bytes.fromhex(metadata["aes_iv"])
salt = bytes.fromhex(metadata["aes_key_salt"])
x = int(metadata["encription_zone_x"])
y = int(metadata["encription_zone_y"])
width = int(metadata["encription_zone_width"])
height = int(metadata["encription_zone_height"])

# generate key from password
key = PBKDF2HMAC(
Expand Down Expand Up @@ -80,15 +80,14 @@ def encrypt(img: Image, password: str, x, y, width, height) -> Image:
iv = os.urandom(16)

# write the iv and salt in the image metadata
metadata = {"iv": iv.hex(),
"salt": salt.hex(),
"algo": "AES-192",
"x": x,
"y": y,
"width": width,
"height": height,
metadata = {"aes_iv": iv.hex(),
"aes_key_salt": salt.hex(),
"encription_zone_x": x,
"encription_zone_y": y,
"encription_zone_width": width,
"encription_zone_height": height,
}
ImageCryptoUtils.__write_metadata(img, metadata)
ImageCryptoUtils._write_metadata(img, metadata)

# create cipher
cipher = Cipher(algorithms.AES(key), modes.CTR(iv))
Expand All @@ -108,7 +107,7 @@ def encrypt(img: Image, password: str, x, y, width, height) -> Image:
return img

@staticmethod
def __write_metadata(img: Image, new_metadata: dict) -> None:
def _write_metadata(img: Image, new_metadata: dict) -> None:
"""
updates the metadata of the image
:param img: image
Expand Down Expand Up @@ -138,10 +137,11 @@ def generate_image_hash(img: Image) -> None:
h = hmac.HMAC(key, hashes.SHA256())
img_bytes = img.tobytes()

iv = bytes.fromhex(ImageCryptoUtils.__read_metadata(img)["iv"])
salt = bytes.fromhex(ImageCryptoUtils.__read_metadata(img)["salt"])
iv = bytes.fromhex(ImageCryptoUtils.__read_metadata(img)["aes_iv"])
salt = bytes.fromhex(ImageCryptoUtils.__read_metadata(img)["aes_key_salt"])
# FIXME
# el key debe ir encriptado con RSA del server
h.update(img_bytes + iv + salt + key)
signature = h.finalize()
ImageCryptoUtils.__write_metadata(img, {"hash": signature.hex(), "key": key.hex()})
img_hash = h.finalize()
ImageCryptoUtils._write_metadata(img, {"hash_key": key.hex()})
return img_hash
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/packages/server/data/users.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[
{
"name": "admin",
"password": "79788a3a2d41a3d716cdfbb3448528966280c3f69fb4ad2fd62074d5579bb1cd",
"salt_p": "976b23b3c923409c8b6b73cd2e7d9dbe"
"password": "526560d5f8e6c94755c20b27e21ab3ab33cd02f632ef811604abb62778ce74d2",
"salt_p": "b8a5101af96448879d51f5a30ca30f7a"
}
]
48 changes: 38 additions & 10 deletions src/packages/server/server.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from .user import User
from PIL import Image, PngImagePlugin
from .storage_manager import StorageManager
from cryptography.hazmat.primitives import hashes, hmac
from cryptography.hazmat.primitives import hashes, hmac, serialization
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.exceptions import InvalidSignature

import re
import uuid

Expand Down Expand Up @@ -112,20 +115,46 @@ def store_image(self, image: Image, user_name, password):

# checK tags #TODO
pass
# check signature #TODO
# check hash signature #TODO

# get metadata
image_metadata = image.info
hash = image_metadata["hash"]
key = bytes.fromhex(image_metadata["key"]) # FIXME el key habra que desencriptarlo

# regenerate hash
img_bytes = image.tobytes()
iv = bytes.fromhex(image_metadata["iv"])
salt = bytes.fromhex(image_metadata["salt"])
iv = bytes.fromhex(image_metadata["aes_iv"])
salt = bytes.fromhex(image_metadata["aes_key_salt"])
key = bytes.fromhex(image_metadata["hash_key"])

h = hmac.HMAC(key, hashes.SHA256())
h.update(img_bytes + iv + salt + key)
signature = h.finalize()
if hash != signature.hex():
raise ValueError("Hashes do not match")
img_hash = h.finalize()


# check hash signature
hash_sign = image_metadata["signature"]
# get public key # FIXME
public_key = image_metadata["public_key"]
public_key = serialization.load_pem_public_key(
bytes.fromhex(public_key)
)
# decript hash signature
try:
public_key.verify(
bytes.fromhex(hash_sign),
img_hash,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
except InvalidSignature:
print("Invalid signature")
return



# check certificate #TODO
pass
# store image
Expand All @@ -139,7 +168,6 @@ def store_image(self, image: Image, user_name, password):
for key, value in image.info.items():
info.add_text(str(key), str(value))
# add new metadata
info.add_text("sample tag", "1234")

# store image
self.__sm.storage_img(image, user_name, info)
Expand Down
22 changes: 11 additions & 11 deletions src/packages/server/storage_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def storage_img(self, img: Image, username: str, metadata) -> None:
"""Stores an image
Args:
img (bytes): image
username (str): name of the image
username (str): name of the author of the image
metadata (dict): metadata of the image
"""
# save image
Expand Down Expand Up @@ -221,8 +221,8 @@ def __get_images_from_date(self, username: str, date: str, time: str = None, num
if time is not None:
try:
return [Image.open(f"{self.__path}/data/images/{username}/{date}/{time}.png")]
except:
# time not found
except Exception as e :
print(f"[ERROR - sm] {e}")
return []

new_date = self.__load_date(date)
Expand All @@ -234,8 +234,8 @@ def __get_images_from_date(self, username: str, date: str, time: str = None, num
images_paths.append({"date": f"{new_date[0]}/{new_date[1]}/{new_date[2]}",
"time": img_time,
"path": f"{self.__path}/data/images/{username}/{new_date[0]}/{new_date[1]}/{new_date[2]}/{time}.png"})
except:
# date not found
except Exception as e:
print(f"[ERROR - sm] {e}")
return []
elif len(new_date) == 2:
try:
Expand All @@ -246,8 +246,8 @@ def __get_images_from_date(self, username: str, date: str, time: str = None, num
images_paths.append({"date": f"{new_date[0]}/{new_date[1]}/{day}",
"time": img_time,
"path": f"{self.__path}/data/images/{username}/{new_date[0]}/{new_date[1]}/{day}/{time}.png"})
except:
# date not found
except Exception as e:
print(f"[ERROR - sm] {e}")
return []
elif len(new_date) == 1:
try:
Expand All @@ -260,8 +260,8 @@ def __get_images_from_date(self, username: str, date: str, time: str = None, num
images_paths.append({"date": f"{new_date[0]}/{month}/{day}",
"time": img_time,
"path": f"{self.__path}/data/images/{username}/{new_date[0]}/{month}/{day}/{time}.png"})
except:
# date not found
except Exception as e:
print(f"[ERROR - sm] {e}")
return []

# get random images
Expand Down Expand Up @@ -302,8 +302,8 @@ def remove_image(self, username: str, date: str, time: str) -> None:
path = f"{self.__path}/data/images/{username}/{date}/{time}.png"
try:
os.remove(path)
except:
# image not found
except Exception as e:
print(f"[ERROR - sm] {e}")
raise ValueError("Image not found")

path = os.path.dirname(path)
Expand Down
6 changes: 3 additions & 3 deletions src/screens/home_screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ def create_main_menu(self):

# DEVELOPER OPTIONS ##################################################
# clear server
# self.main_menu.add_command(label="CLEAN SERVER", command=self.clean_server)
self.main_menu.add_command(label="CLEAN SERVER", command=self.clean_server)
# admin mode
# self.main_menu.add_command(label="LOG AS ADMIN", command=self.admin_mode)
self.main_menu.add_command(label="LOG AS ADMIN", command=self.admin_mode)

def admin_mode(self):
try:
Expand All @@ -88,7 +88,7 @@ def admin_mode(self):
self.app.showUserScreen()

def clean_server(self):
self.app.api.server.clear_server()
self.app.api._server.clear_server()
self.initiate_main_display()
#####################################################################

Expand Down
5 changes: 3 additions & 2 deletions src/screens/image_selector_toplevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class ImageSelectorWindow(tk.Toplevel):
def __init__(self, app):
super().__init__(app.root, background="#212121")
self.geometry("225x550")
self.geometry("225x700")
self.resizable(False, False)
self.title("Image Selector")
self.app = app
Expand Down Expand Up @@ -97,7 +97,8 @@ def check_and_send(self):
self.app.showUserScreen()
self.destroy()
except ValueError as e:
messagebox.showerror("Error", "Invalid values. Make sure you only wrote integers.")
print(e)
messagebox.showerror("Error", f"{e}")


def update_canvas_selection(self):
Expand Down

0 comments on commit 6778eec

Please sign in to comment.