Exemple #1
0
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)
Exemple #2
0
def re_enc_file(file, chunk_size, re_enc_length, seed, key, iv, debug=0):
    """
    Split the file in chunks and apply re-encryption to each of them using the given parameters.
    :param file: file to re-encrypt
    :param chunk_size: chunk size in bytes
    :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 debug: if 1, prints will be shown during execution; default 0, no prints are shown
    """

    # Read file in chunks and re-encrypt each of them with the given parameters
    with open(file, 'rb+') as f:

        # Compute cipher initial value (ONLY FOR CTR MODE)
        enc_block_size = sym.get_cipher(AES.MODE_CTR, None, None, key,
                                        iv).block_size
        init_val = 0

        for file_chunk in iter(lambda: f.read(chunk_size), ''):

            if debug:  # ONLY USE FOR DEBUG
                print('FILE CHUNK TO RE-ENC = (%s) (%d) %s' %
                      (type(file_chunk), len(file_chunk), file_chunk))

            # EOF
            if not len(file_chunk):
                break

            # Re-encrypt file chunk
            re_enc_file_chunk = re_enc.re_encrypt(file_chunk, re_enc_length,
                                                  seed, key, iv, init_val,
                                                  debug)

            if debug:  # ONLY USE FOR DEBUG
                print('RE-ENCRYPTED FILE CHUNK = (%s) (%d) %s' %
                      (type(re_enc_file_chunk), len(re_enc_file_chunk),
                       re_enc_file_chunk))

            # Check re-encryption correctness
            if len(re_enc_file_chunk) != len(file_chunk):
                logging.error(
                    'Re-encrypted file chunk length does not match file chunk length'
                )
                print(
                    '[ERROR] Re-encrypted file chunk length does not match file chunk length'
                )
                raise Exception

            # Replace file chunk with re-encrypted one
            f.seek(-len(re_enc_file_chunk), os.SEEK_CUR)
            f.write(re_enc_file_chunk)

            # Update cipher initial value
            init_val = f.tell() // enc_block_size
Exemple #3
0
def re_decrypt(data=None,
               re_enc_length=const.RE_ENC_LENGTH,
               seed=None,
               key=None,
               iv=None,
               init_val=None,
               debug=0):
    """
    Re-decrypt data using the given parameters.
    :param data: data to re-decrypt
    :param re_enc_length: number of re-encrypted bytes
    :param seed: seed that randomly selected re-encrypted bytes
    :param key: symmetric key to decrypt randomly selected bytes
    :param iv: initialisation vector for the symmetric decryption
    :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-decrypted data
    """

    # Check if data is set
    if data is None:
        logging.error('re_decrypt data exception')
        # if debug:  # ONLY USE FOR DEBUG
        # print('EXCEPTION in re_decrypt data')
        raise Exception

    # Check if key is set
    if key is None:
        logging.error('re_decrypt key exception')
        if debug:  # ONLY USE FOR DEBUG
            print('EXCEPTION in re_decrypt key')
        raise Exception

    # Check if iv is set
    if iv is None:
        logging.error('re_decrypt iv exception')
        if debug:  # ONLY USE FOR DEBUG
            print('EXCEPTION in re_decrypt 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 remove_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.decrypt(sym_cipher, data, debug)
Exemple #4
0
    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
Exemple #5
0
    def write(self, path, buf, offset, fh):

        # self.enc_fp.close()
        # self.enc_fp = open(self._full_path(path), 'wb')

        full_path = self._full_path(path)

        if self.debug:
            print('PATH =', path)
            print('FULL PATH =', full_path)
            print('FH =', fh)
            print('OFFSET =', offset)
            print('BUFF =', buf)
            print('BUFF LEN =', len(buf))

        # Compute file chunks involved in reading process
        starting_aont_chunk_num, ending_aont_chunk_num = self._get_aont_chunks_range(
            offset + len(buf), offset)

        # Check if those chunks have already been processed
        for chunk_num in range(starting_aont_chunk_num,
                               ending_aont_chunk_num + 1):

            # Check if chunk is already in the list, otherwise add it and all previous ones not inside the list
            if str(chunk_num) not in self.file_written_chunks.keys():

                if self.debug:
                    print('Chunk not in already written list')

                for prev_chunk_num in range(chunk_num + 1):
                    if str(prev_chunk_num
                           ) not in self.file_written_chunks.keys():
                        self.file_written_chunks[str(prev_chunk_num)] = 1
                        self.file_read_chunks[str(prev_chunk_num)] = 1

                        if self.debug:
                            print(
                                'Adding chunk #%d to the already written list with value %d'
                                % (prev_chunk_num, self.file_written_chunks[
                                    str(prev_chunk_num)]))

            # Check if chunk has already been processed
            elif not self.file_written_chunks[str(chunk_num)]:

                if self.debug:
                    print('Chunk #%d needs to be processed' % chunk_num)

                # Compute offset on decoded file
                decoded_offset = self._get_decoded_offset(chunk_num)

                if self.debug:
                    print('DECODED OFFSET =', decoded_offset)

                # Compute initial value of cipher block counter
                init_val = self._get_cipher_initial_value(decoded_offset)

                if self.debug:
                    print('INITIAL VALUE =', init_val)

                # 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)

                # Get re-enc parameters
                for i in range(len(self.meta['re_encs'])):
                    self.re_enc_args[i] = self._create_re_enc_params(i)

                # Anti-transform and decrypt chunk
                self._decode(full_path, chunk_num, decoded_offset, sym_cipher,
                             self.re_enc_args)

                # Set relative array chunk position as read
                self.file_written_chunks[str(chunk_num)] = 1
                self.file_read_chunks[str(chunk_num)] = 1

            # Check if chunk is already in the list, otherwise add it and all previous ones not inside the list
            # if str(chunk_num) not in self.file_written_chunks.keys() or not self.file_written_chunks[str(chunk_num)]:
            #
            #     if self.debug:
            #         print('Chunk not in already written list')
            #         print('Chunk #%d needs to be processed' % chunk_num)
            #
            #     # Compute offset on decoded file
            #     decoded_offset = self._get_decoded_offset(chunk_num)
            #
            #     if self.debug:
            #         print('DECODED OFFSET =', decoded_offset)
            #
            #     # Compute initial value of cipher block counter
            #     init_val = self._get_cipher_initial_value(decoded_offset)
            #
            #     if self.debug:
            #         print('INITIAL VALUE =', init_val)
            #
            #     # 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)
            #
            #     # Get re-encryptions parameters
            #     for i in range(len(self.meta['re_encs'])):
            #         self.re_enc_args[i] = self._create_re_enc_params(i)
            #
            #     print('RE ENC ARGS', self.re_enc_args)
            #
            #     # Anti-transform and decrypt chunk
            #     self._decode(full_path, chunk_num, decoded_offset, sym_cipher, self.re_enc_args)
            #
            #     print('WRITE: after decode')
            #
            #     # Set relative array chunk position as read
            #     self.file_written_chunks[str(chunk_num)] = 1

        if self.debug:
            print("writing ", buf, " on ", path, " on tmp fs ", self.temp_fp)

        return super(Abebox, self).write(path, buf, offset,
                                         self.temp_fp.fileno())
Exemple #6
0
    def read(self, path, length, offset, fh):

        # self.enc_fp.close()
        # self.enc_fp = open(self._full_path(path), 'rb')

        full_path = self._full_path(path)

        if self.debug:
            print('READ ===============')
            print('FULL PATH =', full_path)
            print('PATH =', path)
            print('OFFSET =', offset)
            print('LENGTH =', length)

        # Compute length of the plaintext file and the related reading length
        file_size = os.path.getsize(full_path)
        temp_file_size = file_size - (math.ceil(
            file_size / self.meta['chunk_size']) * self.meta['random_size'])
        real_len = min(offset + length, temp_file_size)

        # Compute file chunks involved in reading process
        starting_aont_chunk_num, ending_aont_chunk_num = self._get_aont_chunks_range(
            real_len, offset)

        # Check if those chunks have already been processed
        for chunk_num in range(starting_aont_chunk_num,
                               ending_aont_chunk_num + 1):
            # Check if chunk is already in the list, otherwise add it and all previous ones not inside the list
            if str(chunk_num) not in self.file_read_chunks.keys():

                if self.debug:
                    print('Chunk not in already read list')

                for prev_chunk_num in range(chunk_num + 1):
                    if str(prev_chunk_num) not in self.file_read_chunks.keys():
                        self.file_read_chunks[str(prev_chunk_num)] = 0

                        if self.debug:
                            print(
                                'Adding chunk #%d to the already read list with value %d'
                                % (prev_chunk_num,
                                   self.file_read_chunks[str(prev_chunk_num)]))

            # Check if chunk has already been processed
            if not self.file_read_chunks[str(chunk_num)]:

                if self.debug:
                    print('Chunk #%d needs to be processed' % chunk_num)

                # Compute offset on decoded file
                decoded_offset = self._get_decoded_offset(chunk_num)

                if self.debug:
                    print('DECODED OFFSET =', decoded_offset)

                # Compute initial value of cipher block counter
                init_val = self._get_cipher_initial_value(decoded_offset)

                if self.debug:
                    print('INITIAL VALUE =', init_val)

                # 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)

                # Get re-encryptions parameters
                for i in range(len(self.meta['re_encs'])):
                    self.re_enc_args[i] = self._create_re_enc_params(i)

                # Anti-transform and decrypt chunk
                self._decode(full_path, chunk_num, decoded_offset, sym_cipher,
                             self.re_enc_args)

                # Set relative array chunk position as read
                self.file_read_chunks[str(chunk_num)] = 1

        if self.debug:
            print("reading ", length, " bytes on tmp fs ", self.temp_fp)

        #print('READ', time() * 1000.0 - self.starting_time)

        return super(Abebox, self).read(path, length, offset,
                                        self.temp_fp.fileno())
Exemple #7
0
 def _get_cipher_initial_value(self, offset):
     """
     Return the initial value to set as cipher block counter for the given offset
     """
     return offset // sym.get_cipher(AES.MODE_CTR, None, None, self.meta['sym_key'][:16], self.meta['nonce'])\
         .block_size