class Decoder: MODES = {'GCM': 8} MODE_LENGTH = 1 def __init__(self, password, image_folder_path): self.image_folder_path = image_folder_path self.mode = None self._gcm = None self._password = password self._data_length = 0 self.extractor = Extractor(image_folder_path) def get_header_length(self): return GCM.get_iv_length() + GCM.get_salt_length() def decode_header(self, raw_header): # assume raw_header is bytearray of values salt_end = GCM.get_salt_length() gcm_end = salt_end + GCM.get_iv_length() password_salt = bytes(raw_header[:salt_end]) iv = bytes(raw_header[salt_end:gcm_end]) self._gcm = GCM(iv=iv, password_salt=password_salt) self._gcm.make_key(self._password) del self._password def get_tag(self, raw_data): tag = bytes(raw_data[-GCM.get_tag_length():]) self._gcm.set_tag(tag) def decrypt_and_save_data(self, raw_data, destination_file): decrypted = self._gcm.decrypt( raw_data[self.get_header_length():-GCM.get_tag_length()]) # with open("temp", "wb") as f: # f.write(decrypted) self._gcm.decrypt_finalize() with open(destination_file, "wb") as f: f.write(decrypted) def decode_file(self, file_path): raw_data = self.extractor.load_images() # with open("decode-test", "wb") as f: # f.write(raw_data) raw_header = raw_data[:self.get_header_length()] self.decode_header(raw_header) self.get_tag(raw_data) self.decrypt_and_save_data(raw_data, file_path)
class Encoder: MODES = {'GCM': 8} def __init__(self, password, source_image_folder_path, destination_image_folder_path, mode='GCM'): self.mode = Encoder.MODES[mode] self.source_image_folder_path = source_image_folder_path self.destination_image_folder_path = destination_image_folder_path if os.path.exists(self.destination_image_folder_path): shutil.rmtree(self.destination_image_folder_path) os.makedirs(self.destination_image_folder_path) self.gcm = GCM() self.gcm.make_key(password) self.transcriber = Transcriber(self.mode, source_image_folder_path, destination_image_folder_path) def encode_file(self, file_path): with open(file_path, 'rb') as source: file_bytes = source.read() encrypted = self.gcm.encrypt(file_bytes) tag = self.gcm.encrypt_finalize() header = self.gcm.password_salt + self.gcm.iv full_length = len(header) + len(encrypted) + len(tag) # if not self.transcriber.can_fit_bytes(full_length): # print("Not enough images to store the necessary data") # exit() self.transcriber.choose_needed_images(full_length) print("full length", full_length, full_length * 8) self.transcriber.set_encoding(header + encrypted + tag) # with open("encode-test", "wb") as f: # f.write(header + encrypted + tag) self.transcriber.finish_encoding()