def apply_punctured_enc(data, re_enc_length, seed, key, iv, init_val, debug=0): """ Apply punctured encryption to the given data: 're_enc_length' bytes are randomly selected using the seed and symmetrically encrypted using the given key and iv. :param data: data to re-encrypt :param re_enc_length: number of bytes to re-encrypt :param seed: seed to randomly select bytes to re-encrypt :param key: symmetric key to encrypt randomly selected bytes :param iv: initialisation vector for the symmetric encryption :param init_val: initial value (ONLY FOR CTR MODE) :param debug: if 1, prints will be shown during execution; default 0, no prints are shown :return: re-encrypted data """ # Get random bytes to re-encrypt and their positions in the data bytes_to_re_enc, re_enc_indexes = get_bytes_to_re_enc( data, re_enc_length, seed, debug) if debug: # ONLY USE FOR DEBUG print('BYTES TO RE-ENCRYPT = (%d) %s' % (len(bytes_to_re_enc), bytes_to_re_enc)) print('INDEX TO RE-ENCRYPT = (%d) %s' % (len(re_enc_indexes), re_enc_indexes)) # Re-encrypt random data bytes sym_cipher = sym.get_cipher(AES.MODE_CTR, init_val, None, key, iv) re_enc_bytes = sym.encrypt(sym_cipher, bytes_to_re_enc, debug) if debug: # ONLY USE FOR DEBUG print('RE-ENCRYPTED BYTES = (%s) (%d) %s' % (type(re_enc_bytes), len(re_enc_bytes), re_enc_bytes)) # Replace bytes with re-encrypted ones in data return replace_bytes(data, re_enc_bytes, re_enc_indexes, debug)
def re_encrypt(data=None, re_enc_length=const.RE_ENC_LENGTH, seed=None, key=None, iv=None, init_val=None, debug=0): """ Re-encrypt data using the given parameters. :param data: data to re-encrypt :param re_enc_length: number of bytes to re-encrypt :param seed: seed to randomly select bytes to re-encrypt :param key: symmetric key to encrypt randomly selected bytes :param iv: initialisation vector for the symmetric encryption :param init_val: initial value (ONLY FOR CTR MODE) :param debug: if 1, prints will be shown during execution; default 0, no prints are shown :return: re-encrypted data """ # Check if data is set if data is None: logging.error('re_encrypt data exception') if debug: # ONLY USE FOR DEBUG print('EXCEPTION in re_encrypt data') raise Exception # Check if key is set if key is None: logging.error('re_encrypt key exception') if debug: # ONLY USE FOR DEBUG print('EXCEPTION in re_encrypt key') raise Exception # Check if iv is set if iv is None: logging.error('re_encrypt iv exception') if debug: # ONLY USE FOR DEBUG print('EXCEPTION in re_encrypt iv') raise Exception # Check if the number of bytes to re-encrypt is lesser than the data length if re_enc_length < len(data): # Apply punctured encryption return apply_punctured_enc(data, re_enc_length, seed, key, iv, init_val, debug) else: # Re-encryption of the whole data sym_cipher = sym.get_cipher(AES.MODE_CTR, init_val, None, key, iv) return sym.encrypt(sym_cipher, data, debug)
def release(self, path, fh): #self.starting_time = time() * 1000.0 if self.debug: print("Releasing file ", path) # Create AES cipher # sym_cipher = AES.new(self.meta['sym_key'][:16], AES.MODE_CTR, nonce=self.meta['nonce']) # rewind file, adjust read_in_chucnk # print("Release: closing, removing and open again file ", self._full_path(path)) # os.close(fh) # print("close done") # os.remove(self._full_path(path)) # print("rm done") # fh = os.open(self._full_path(path), os.O_WRONLY | os.O_CREAT) # print("re-opening file") # fh = open(self._full_path(path), 'wb+') # print("re-opening file done") # print("seeking fh") # os.lseek(fh, 0, os.SEEK_SET) # Reset file pointer self.temp_fp.seek(0) if self.debug: print("Temporary file has size : ", self.temp_fp.seek(0, os.SEEK_END)) # self.temp_fp.seek(0) # Get re-encryptions parameters #re_enc_args = [] re_enc_ops_num = len(self.meta['re_encs']) #for re_enc_op in self.meta['re_encs']: # re_enc_args.append(self._create_re_enc_params(re_enc_op)) # Write only modified file chunks for chunk_num in self.file_written_chunks.keys(): if self.debug: print('CHUNK NUM # =', chunk_num, self.file_written_chunks[chunk_num]) if self.file_written_chunks[chunk_num]: if self.debug: print("release written chunk #", chunk_num) # print("release - read chunk #", chunk) # os.write(fh, sym_cipher.encrypt(chunk)) # fh.write(sym_cipher.encrypt(chunk)) # Read file chunk # Set file pointer to file chunk starting byte self.temp_fp.seek( int(chunk_num) * (self.meta['chunk_size'] - self.meta['random_size'])) # Read a file chunk from temporary file chunk = self.temp_fp.read(self.meta['chunk_size'] - self.meta['random_size']) if self.debug: print('in release, read %d bytes = %s' % (len(chunk), chunk)) # Compute offset on decoded file decoded_offset = self._get_decoded_offset(int(chunk_num)) # Compute initial value of cipher block counter init_val = self._get_cipher_initial_value(decoded_offset) # Create symmetric cipher with proper initial value sym_cipher = sym.get_cipher(AES.MODE_CTR, init_val, None, self.meta['sym_key'][:16], self.meta['nonce'], self.debug) #elapsed_time = (time() * 1000.0) - starting_time #elapsed_time_from_beginning = (time() * 1000.0) - self.starting_time #print('[{}] [{}] ** RELEASE - chunk {} after sym.get_cipher **'.format(elapsed_time_from_beginning, elapsed_time, chunk_num)) # Encrypt file chunk enc_chunk = sym.encrypt(sym_cipher, chunk, self.debug) # enc_chunk = chunk # Transform encrypted file chunk if self.debug: print("Applying AONT to newly encrypted chunk") # Get AONT parameters aont_args = self._create_aont_transf_params(len(enc_chunk)) # Apply AONT to the encrypted chunk transf_enc_chunk = aont.transform(enc_chunk, aont_args, self.debug) #elapsed_time = (time() * 1000.0) - starting_time #elapsed_time_from_beginning = (time() * 1000.0) - self.starting_time #print('[{}] [{}] ** RELEASE - chunk {} after aont.transform **'.format(elapsed_time_from_beginning, elapsed_time, chunk_num)) if self.debug: print("AONT successfully applied") # If previously applied, re-apply re-encryptions re_enc_transf_enc_chunk = transf_enc_chunk re_enc_init_val = self._get_cipher_initial_value( int(chunk_num) * self.meta['chunk_size']) if re_enc_ops_num: if self.debug: print("Re-applying re-encryptions to file chunk") for i in range(re_enc_ops_num): # Get re-encryptions parameters self.re_enc_args[i] = self._create_re_enc_params(i) # Add other params to re-encryption params self.re_enc_args[i]['init_val'] = re_enc_init_val # Re-encrypt transformed encrypted chunk re_enc_transf_enc_chunk = re_enc.apply_old_re_enc( re_enc_transf_enc_chunk, self.re_enc_args[i], self.debug) if self.debug: print("RE-ENCRYPTED CHUNK = (%d) %s" % (len(re_enc_transf_enc_chunk), re_enc_transf_enc_chunk)) print("Re-encryption successfully re-applied") #elapsed_time = (time() * 1000.0) - starting_time #elapsed_time_from_beginning = (time() * 1000.0) - self.starting_time #print('[{}] [{}] ** RELEASE - chunk {} after all re_enc_op **'.format(elapsed_time_from_beginning, elapsed_time, chunk_num)) if self.debug: print("Re-encryptions successfully re-applied") if self.debug: print('WRITING FH =', fh) print('CHUNK =', re_enc_transf_enc_chunk) # Compute offset on encoded file encoded_offset = self._get_encoded_offset(int(chunk_num)) # Write transformed encrypted chunk os.lseek(fh, encoded_offset, os.SEEK_SET) os.write(fh, re_enc_transf_enc_chunk) # os.write(fh, chunk + 32*b'a') if self.debug: print("chunk (%d) %s has been written on file %d" % (len(re_enc_transf_enc_chunk), re_enc_transf_enc_chunk, fh)) # with open(self._full_path(path), 'wb+') as enc_fp: # print("Release: file opened with fp ", enc_fp) # print("release: writing back from tempfile", self.temp_fp.file.name) # for chunk in self._read_in_chunks(self.temp_fp, self.CHUNK_SIZE): # print("release - read chunk" , chunk) # enc_fp.write(sym_cipher.encrypt(chunk)) if self.debug: print("Closing fs") os.close(fh) if self.debug: print("Closed") meta_directory = self.dirname + '/.abebox/' if not os.path.exists(meta_directory): os.makedirs(meta_directory) if self.debug: print("dumping meta on :", meta_directory + self.filename) if sum(self.file_written_chunks.values()): self._dump_meta(meta_directory + self.filename) #elapsed_time = (time() * 1000.0) - starting_time #elapsed_time_from_beginning = (time() * 1000.0) - self.starting_time #print('[{}] [{}] ** RELEASE END **'.format(elapsed_time_from_beginning, elapsed_time)) #print('RELEASE', time() * 1000.0 - self.starting_time) self.enc_fp.close() self.temp_fp.close() return