From ecc1cc667bb4690579bc3010847610cd96213564 Mon Sep 17 00:00:00 2001 From: shim_ <> Date: Sat, 21 Jul 2018 14:02:15 +0200 Subject: [PATCH] implemented derived passwords --- imports/encryptedscreenshot.py | 8 ++++---- imports/hashderive.py | 30 ++++++++++++++++++++++++++++++ imports/processors.py | 29 +++++++++++++++++++++++------ 3 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 imports/hashderive.py diff --git a/imports/encryptedscreenshot.py b/imports/encryptedscreenshot.py index ba655d9..128a7ca 100644 --- a/imports/encryptedscreenshot.py +++ b/imports/encryptedscreenshot.py @@ -9,13 +9,12 @@ import os, struct, time, hashlib, hashlib, random, binascii class EncryptedScreenshot: - def __init__(self, metadata,id=None,signer=None,password_encryptor=None): + def __init__(self, metadata,password=None,id=None,signer=None,password_encryptor=None): def rand(len): return ''.join( random.choice("1234567890ABCDEFGHIJKLMNOPQRSTUWVXYZabcdefghijklmnopqrstuwvxyz") for _ in range(len)) - self.password = rand(16) - print("Passphrase %s" % binascii.hexlify(self.passphrase())) + self.password = (password or rand(16)) self.id = id if id is None: self.id = rand(8) @@ -60,7 +59,8 @@ class EncryptedScreenshot: fields = { "image": encrypted_image, "metadata_encryption": self.metadata_encryption, - "metadata": encrypted_metadata if self.metadata_encryption else self.metadata + "metadata": encrypted_metadata if self.metadata_encryption else self.metadata, + "public_metadata": self.metadata["public"] } if self.signer is not None: diff --git a/imports/hashderive.py b/imports/hashderive.py new file mode 100644 index 0000000..93f978f --- /dev/null +++ b/imports/hashderive.py @@ -0,0 +1,30 @@ +import hashlib + +import binascii + +class HashDerivedKey: + + @staticmethod + def from_hex(hex_str): + return HashDerivedKey(bytes(bytearray.fromhex(hex_str))) + + def __init__(self, master): + def ensure_bytes(b): + assert isinstance(b, bytes) + return b + ensure_bytes(master) + def derive(seed): + ensure_bytes(seed) + sha = hashlib.sha256() + sha.update(master) + sha.update(seed) + return sha.digest() + hex = lambda b: binascii.hexlify(b).decode("utf-8") + self.master = master + self.master_hex = lambda: hex(master) + self.derive = derive + self.derive_hex = lambda seed: hex(derive(seed)) + + def derive_metadata(self,seed): + key = self.derive(seed) + return (key,{"key_seed": binascii.hexlify(seed).decode("utf-8")}) diff --git a/imports/processors.py b/imports/processors.py index c9f0aa6..a5f7c9b 100644 --- a/imports/processors.py +++ b/imports/processors.py @@ -1,7 +1,8 @@ import time from encryptedscreenshot import EncryptedScreenshot, Signer -import getpass, os +from hashderive import HashDerivedKey +import getpass, os, sys from PythonQt.QtGui import QInputDialog from PythonQt.QtCore import QSettings from seafapi import * @@ -36,13 +37,17 @@ class EncryptedProcessor(Processor): def __init__(self,seaf_lib,lib_path): self.seaf_lib = seaf_lib self.lib_path = lib_path + self.host = None + self.derived_key = HashDerivedKey(os.urandom(32)) self.load_settings() def load_settings(self): settings = QSettings() settings.beginGroup("uploaders") settings.beginGroup("seafile") - self.host = settings.value("encscreen-url", "") + self.host = settings.value("encscreen-url", None) + if settings.value("encscreen-derived-key", None): + self.derived_key = HashDerivedKey.from_hex(settings.value("encscreen-derived-key", None)) settings.endGroup() settings.endGroup() @@ -51,6 +56,7 @@ class EncryptedProcessor(Processor): settings.beginGroup("uploaders") settings.beginGroup("seafile") settings.setValue("encscreen-url", self.host) + if self.derived_key: settings.setValue(self.derived_key.master_hex()) settings.endGroup() settings.endGroup() @@ -58,17 +64,28 @@ class EncryptedProcessor(Processor): return self.host is not None and self.host != "" def configure(self,parent): - self.host = QInputDialog.getText(parent, 'Encscreen Server Setup', 'Enter server url (ex. https://servertld/s#%id%key):', text="https://screens.shimun.net/s#%id%key") + self.host = QInputDialog.getText(parent, 'Encscreen Server Setup', 'Enter server url (ex. https://servertld/s#%id%key):', text=(self.host or "https://screens.shimun.net/s#%id%key")) + master = QInputDialog.getText(parent, 'Encscreen Master Key Setup', 'Enter master key (hex encoded):', text=(self.derived_key.master_hex() if self.derived_key else "")) + try: + self.derived_key = HashDerivedKey.from_hex(master) + except: + self.derived_key = HashDerivedKey(os.urandom(32)) self.save_settings() def upload(self,file,name): - enrypted = EncryptedScreenshot({ + def derive(): + seed = os.urandom(16) + (_, key_meta) = self.derived_key.derive_metadata(seed) + return (self.derived_key.derive_hex(seed)[0:16], key_meta) + (key, key_meta) = derive() + enrypted = EncryptedScreenshot(metadata = { "owner": getpass.getuser(), "format": str(file).split('.')[-1], "title": name, "timestamp": int(time.time() * 1000), - "size": os.stat(file).st_size - },signer=Signer.default()) + "size": os.stat(file).st_size, + "public": key_meta + },password=key,signer=Signer.default()) tmpHandle = open(file + "c", 'wb') tmpHandle.write(enrypted.assemble(file)) tmpHandle.close()