def __str__(self): import base64 from Publication import Publication general_flags_str = 'General flags: ' if self.is_deadman_switch_file(): general_flags_str += 'Deadman Switch File' elif self.is_deadman_switch_key(): general_flags_str += 'Deadman Switch Key' else: general_flags_str += 'None' s = '' if self.temporal_key is not None: s = "Temporal Key: %s\n" % binascii.hexlify( self.temporal_key).decode('ascii') return "PartialFile:\n\tInitial TXID: %s\n\tSanitized filename: %s\n\tDescription: %s\n\tFile size: %d\n\tEncryption type: %s\n\tContent type: %s\n\tCompression type: %s\n\t%s\n\tFile hash: %s\n\tFile pointer: %d\n\tACK Window: %s\n\t%s\n\tInitial block number: %d\n\tFinal block number: %d\n\tSQL ID: %d\n\tIs deadman switch file: %s\n\tIs deadman switch key: %s\n\tIs complete deadman switch file: %r\n\tIs complete: %r\n" % ( self.initial_txid, self.sanitized_filename, self.description, self.file_size, Publication.get_encryption_str( self.encryption_type), Publication.get_content_type_str(self.content_type), Publication.get_compression_type_str( self.compression_type), general_flags_str, binascii.hexlify(self.file_hash).decode('ascii'), self.file_ptr, self.block_acks, s, self.initial_block_num, self.final_block_num, self.sql_id, self.is_deadman_switch_file(), self.is_deadman_switch_key(), self.is_complete_deadman_switch_file(), self.is_complete())
def __str__(self): import base64 from Publication import Publication general_flags_str = 'General flags: ' if self.is_deadman_switch_file(): general_flags_str += 'Deadman Switch File' elif self.is_deadman_switch_key(): general_flags_str += 'Deadman Switch Key' else: general_flags_str += 'None' s = '' if self.temporal_key is not None: s = "Temporal Key: %s\n" % binascii.hexlify(self.temporal_key).decode('ascii') return "PartialFile:\n\tInitial TXID: %s\n\tSanitized filename: %s\n\tDescription: %s\n\tFile size: %d\n\tEncryption type: %s\n\tContent type: %s\n\tCompression type: %s\n\t%s\n\tFile hash: %s\n\tFile pointer: %d\n\tACK Window: %s\n\t%s\n\tInitial block number: %d\n\tFinal block number: %d\n\tSQL ID: %d\n\tIs deadman switch file: %s\n\tIs deadman switch key: %s\n\tIs complete deadman switch file: %r\n\tIs complete: %r\n" % (self.initial_txid, self.sanitized_filename, self.description, self.file_size, Publication.get_encryption_str(self.encryption_type), Publication.get_content_type_str(self.content_type), Publication.get_compression_type_str(self.compression_type), general_flags_str, binascii.hexlify(self.file_hash).decode('ascii'), self.file_ptr, self.block_acks, s, self.initial_block_num, self.final_block_num, self.sql_id, self.is_deadman_switch_file(), self.is_deadman_switch_key(), self.is_complete_deadman_switch_file(), self.is_complete())
def finalize(self, temporal_key, block_num): from Publication import Publication from Utils import Utils # If not all bytes were received, this is a failure. if (not self.is_complete()) and ( not self.is_complete_deadman_switch_file()): self.d("Cannot finalize because file is not complete!") return False # Update the temporal key, if there is one. if (self.encryption_type != Publication.ENCRYPTION_TYPE_NONE) and \ (temporal_key != (b'\x00' * 32)): self.temporal_key = temporal_key # If file is in plaintext, the hash is in the temporal key field. if self.encryption_type == Publication.ENCRYPTION_TYPE_NONE: self.file_hash = temporal_key self.temporal_key = b'\x00' * 32 # Read the file we extracted. file_bytes = None with open(self.file_path, 'rb') as f: file_bytes = f.read() # Calculate the hash of the file we extracted. calculated_hash = hashlib.sha256(file_bytes).digest() # Check that the hash in the publication header matches what we have. if self.file_hash != calculated_hash: self.d("Hashes do not match!:\n%s\n%s" % (binascii.hexlify(self.file_hash).decode('ascii'), binascii.hexlify(calculated_hash).decode('ascii'))) return False # If this file is a deadman switch, don't try to decrypt, since we don't # have the real key here. if self.is_deadman_switch_file() and (temporal_key == (b'\xff' * 32)): # Save the num_parallel_txs and encryption_type so that when the key # is found in the future, we know how to decrypt this. self.final_block_num = block_num self.save_state() return True # Get a unique filename in the output directory. new_file_path = PartialFile.get_unique_filepath( self.initial_txid, self.output_dir, self.sanitized_filename) # Decrypt the file, if necessary. if self.encryption_type == Publication.ENCRYPTION_TYPE_GPG2_AES256_SHA512: self.d("File is encrypted with type %s. Decrypting..." % Publication.get_encryption_str(self.encryption_type)) file_bytes = Utils.decrypt(file_bytes, self.temporal_key) if len(file_bytes) == 0: self.d("Decryption of file yielded zero bytes!") return False # Write the plaintext bytes into the output directory. with open(new_file_path, 'wb') as f: f.write(file_bytes) # Remove the encrypted file. try: os.unlink(self.file_path) except FileNotFoundError: pass else: # Move file out of partial directory into output directory. os.rename(self.file_path, new_file_path) # Update the file_path with its final destination. self.file_path = new_file_path # Delete the state file. try: os.unlink(self.state_file) except FileNotFoundError: pass # Update the final block number. self.final_block_num = block_num # Mark as finalized and return success. self.finalized = True return True
def finalize(self, temporal_key, block_num): from Publication import Publication from Utils import Utils # If not all bytes were received, this is a failure. if (not self.is_complete()) and (not self.is_complete_deadman_switch_file()): self.d("Cannot finalize because file is not complete!") return False # Update the temporal key, if there is one. if (self.encryption_type != Publication.ENCRYPTION_TYPE_NONE) and \ (temporal_key != (b'\x00' * 32)): self.temporal_key = temporal_key # If file is in plaintext, the hash is in the temporal key field. if self.encryption_type == Publication.ENCRYPTION_TYPE_NONE: self.file_hash = temporal_key self.temporal_key = b'\x00' * 32 # Read the file we extracted. file_bytes = None with open(self.file_path, 'rb') as f: file_bytes = f.read() # Calculate the hash of the file we extracted. calculated_hash = hashlib.sha256(file_bytes).digest() # Check that the hash in the publication header matches what we have. if self.file_hash != calculated_hash: self.d("Hashes do not match!:\n%s\n%s" % (binascii.hexlify(self.file_hash).decode('ascii'), binascii.hexlify(calculated_hash).decode('ascii'))) return False # If this file is a deadman switch, don't try to decrypt, since we don't # have the real key here. if self.is_deadman_switch_file() and (temporal_key == (b'\xff' * 32)): # Save the num_parallel_txs and encryption_type so that when the key # is found in the future, we know how to decrypt this. self.final_block_num = block_num self.save_state() return True # Get a unique filename in the output directory. new_file_path = PartialFile.get_unique_filepath(self.initial_txid, self.output_dir, self.sanitized_filename) # Decrypt the file, if necessary. if self.encryption_type == Publication.ENCRYPTION_TYPE_GPG2_AES256_SHA512: self.d("File is encrypted with type %s. Decrypting..." % Publication.get_encryption_str(self.encryption_type)) file_bytes = Utils.decrypt(file_bytes, self.temporal_key) if len(file_bytes) == 0: self.d("Decryption of file yielded zero bytes!") return False # Write the plaintext bytes into the output directory. with open(new_file_path, 'wb') as f: f.write(file_bytes) # Remove the encrypted file. try: os.unlink(self.file_path) except FileNotFoundError: pass else: # Move file out of partial directory into output directory. os.rename(self.file_path, new_file_path) # Update the file_path with its final destination. self.file_path = new_file_path # Delete the state file. try: os.unlink(self.state_file) except FileNotFoundError: pass # Update the final block number. self.final_block_num = block_num # Mark as finalized and return success. self.finalized = True return True