def __recover_message(self, mediate_length, key): """ After extraction is completed, call this method to decode and extract original message. :param mediate_length: the mediate length of hidden message (necessary to perform decoding) :return: extracted message """ if not mediate_length: mediate_length = mediate_length if mediate_length <= 0: raise AttributeError('Necessary argument not specified!') if len(self.message_to_proc_part) > mediate_length: self.message_to_proc_part = self.message_to_proc_part[:mediate_length] elif len(self.message_to_proc_part) < mediate_length: raise RuntimeError("Couldn't extract message with provided argument.") # print self.message_to_proc_part.tolist() s = int(math.ceil(math.sqrt(len(self.message_to_proc_part) / StegoCore.BITS))) try: msg_matrix_encoded_array = np.reshape(self.message_to_proc_part, (s, s, StegoCore.BITS)) except ValueError: print colorize("Wrong session key. Can't extract message.", COLORS.FAIL) return '' msg_matrix_encoded = sh.bits_matrix_to_int_matrix(msg_matrix_encoded_array) msg_matrix = QMatrix.decode_matrix_message(msg_matrix_encoded, key) msg = sh.matrix_to_message(msg_matrix) return msg
def __configure_for_stream_mode(self, stream_mode, **kwargs): """ Configure session for specified stream mode :param stream_mode: :param kwargs: :return: """ print "Configurating..." self.stream_mode = stream_mode if stream_mode == StreamMode.StreamFromFileToFile: # file to file input = kwargs[KEY_INPUT_FILE_NAME] self.stego_mode = kwargs[KEY_STEGO_MODE] self.file_source = wave.open(input, 'rb') if self.stego_mode == StegoMode.Hide: self.output_wave_file = wave.open(kwargs[KEY_OUTPUT_FILE_NAME], 'wb') self.output_wave_file.setnchannels( self.file_source.getnchannels()) self.output_wave_file.setsampwidth( self.file_source.getsampwidth()) self.output_wave_file.setframerate( self.file_source.getframerate()) self.enable_processing = True elif stream_mode == StreamMode.StreamFromBuildInInputToSoundFlower: # build-in input to sound flower self.stego_mode = StegoMode.Hide elif stream_mode == StreamMode.StreamFromSoundFlowerToBuildInOutput: # sound flower to build-in output self.stego_mode = StegoMode.Recover else: print colorize("Unsupported stream mode! [%i]" % self.stream_mode, COLORS.FAIL)
def __hide(self, chunk_source, chunk_container): """ Hide message part in container :param chunk: chunk to be used as container :return: processed or the original chunk """ container_processed, self.message_to_proc_part = self.gsc.hide(chunk_source, chunk_container, self.message_to_proc_part) if not len(self.message_to_proc_part): print colorize("Message integrated.", COLORS.OKBLUE) return chunk_source, container_processed
def scan(self): """ Begin synchronization and message extraction. """ if not (self.stream_mode == StreamMode.StreamFromSoundFlowerToBuildInOutput or self.stream_mode == StreamMode.StreamFromFileToFile): print colorize("Not applicable for current stream mode!", COLORS.FAIL) return print colorize("Begin scanning...", COLORS.OKGREEN) self.enable_processing = True
def deserialize(self, filename=SETTINGS_FILE_NAME): if os.path.isfile(filename): with open(filename, 'r') as infile: data = json.load(infile) self.frames_to_skip = data[SETTING_KEY_FRAMES_TO_SKIP] self.frame_size = data[SETTINGS_KEY_FRAME_SIZE] self.sync_mark = data[SETTINGS_KEY_SYNC_MARK] self.security_or_capacity = data[SETTINGS_SECURITY_OR_CAPACITY] self.build_in_input_audio_device_name = data[SETTINGS_KEY_BUILD_IN_INPUT] self.build_in_output_audio_device_name = data[SETTINGS_KEY_BUILD_IN_OUTPUT] self.virtual_audio_device_name = data[SETTINGS_KEY_VIRTUAL_DEVICE] else: print colorize("%s couldn't be found. Applying default settings." % SETTINGS_FILE_NAME, COLORS.FAIL) self.serialize() self.deserialize()
def do_connect(self, line): """ Create session with specified mode. usage: connect m=<mode>&d=<debug> :param mode: 0 - record sound from mic, hide message and redirect it to SoundFlower virtual device 1 - receive sound from SoundFlower virtual device, recover message and play it in dynamics :param debug 0 - false (default) 1 - true """ args = urlparse.parse_qs(line) try: mode = int(args['m'][0]) except KeyError: mode = 0 try: self.debug = bool(args['d'][0]) if self.debug: print colorize("Debug mode.", COLORS.WARNING) except KeyError: pass if not (mode == StreamMode.StreamFromBuildInInputToSoundFlower or mode == StreamMode.StreamFromSoundFlowerToBuildInOutput): self.print_err(inspect.currentframe().f_code.co_name.replace( 'do_', '')) return # load settings settings = StegoSettings.Instance() settings.deserialize() if settings.validate_stream_mode(mode): self.session = StegoScramblerSession( mode, **{ StegoCore.SYNC_MARK_KEY: settings.sync_mark, StegoCore.SECURITY_OR_CAPACITY: settings.security_or_capacity }) self.session.open_stream() else: print colorize( "There are no supported audio devices for current stream mode.", COLORS.FAIL)
def recover(self, session_key, user_key, msg_file_name): """ Extract and decode message, save it to file :param session_key: :param user_key: :return: """ if not (self.stream_mode == StreamMode.StreamFromSoundFlowerToBuildInOutput or self.stream_mode == StreamMode.StreamFromFileToFile): print colorize("Not applicable for current stream mode!", COLORS.FAIL) return message = self.core.recover(session_key, user_key) gs_io.save_message_to_file(msg_file_name, message) if not message == '': print colorize("Message recovered.", COLORS.OKGREEN)
def __init__(self, stego_mode, **kwargs): """ Init core class instance. :param stego_mode: StegoMode.Hide or StegoMode.Recover :param kwargs: 1) StegoMode.Hide - necessary keys: a) StegoCore.SKIP_FRAMES_KEY - number of frames to skip before integration [optional] b) StegoCore.SYNC_MARK_KEY - text marker to perform synchronization [optional] 2) StegoMode.Recover - optional key: a) StegoCore.SKIP_FRAMES_KEY - number of frames to skip before integration [optional] b) StegoCore.SYNC_MARK_KEY - text marker to perform synchronization [optional] """ self.stego_mode = stego_mode # encode or decode self.message_to_proc_part = np.empty(0, dtype=np.int8) # the part of message that left to be integrated self.skip_frames = 0 # how many frames shoud be skipped self.mediate_length = 0 # length of message to recover (length of bits array) self.security_or_capacity = 0 # synchronization self.sync_mark = '' # synchronization mark self.sync_mark_encoded_array = np.empty(0, dtype=np.int8) # synchronization mark encoded self.sync_mark_temp_encoded_array = [] # list that may contain sync mark if stego_mode == StegoMode.Hide: if StegoCore.SKIP_FRAMES_KEY in kwargs: # set number of frames to skip self.skip_frames = kwargs[StegoCore.SKIP_FRAMES_KEY] else: if StegoCore.SKIP_FRAMES_KEY in kwargs: # set number of frames to skip self.skip_frames = kwargs[StegoCore.SKIP_FRAMES_KEY] if StegoCore.SYNC_MARK_KEY in kwargs: self.sync_mark = kwargs[StegoCore.SYNC_MARK_KEY] self.__synchronization_prepare() if StegoCore.SECURITY_OR_CAPACITY in kwargs: self.security_or_capacity = kwargs[StegoCore.SECURITY_OR_CAPACITY] self.gsc = gsc_core.PyCore(self.sync_mark_encoded_array, 1024, 3 * 1024, self.security_or_capacity) else: print colorize("Error: no sync mark provided", COLORS.FAIL)
def hide(self, msg_file_name, key, recover_info_filename=RECOVER_INFO_DEFAULT_FILE_NAME): """ Load message and call core method to begin integration. :param msg_file_name: file name of the file with message :param key: key to encode message """ if not (self.stream_mode == StreamMode.StreamFromBuildInInputToSoundFlower or self.stream_mode == StreamMode.StreamFromFileToFile): print colorize("Not applicable for current stream mode!", COLORS.FAIL) # load mesage message = gs_io.load_message_from_file(msg_file_name) if not message == '': print colorize("Begin integration...", COLORS.OKBLUE) session_key = self.core.hide(message, key) gs_io.save_data_to_recover(recover_info_filename, session_key) self.enable_processing = True else: print colorize("Wrong or empty file with message!", COLORS.FAIL)
def print_err(self, fa_name): print colorize("Wrong arguments. Type `help " + fa_name + "`", COLORS.FAIL)
def __init__(self): cmd.Cmd.__init__(self) self.session = None self.debug = False print colorize("Welcome!", COLORS.WARNING)
def main(opts): input_container_file_name = '' message_file_name = '' output_container_file_name = '' key = -1 message_length = -1 recover_info_file_name = RECOVER_INFO_DEFAULT_FILE_NAME # -------------------------------------- # print colorize("Debug mode.", COLORS.WARNING) # # -------------------------------------- # hide = True # #hide = False # # -------------------------------------- # if hide: # # -------------------------------------- # input_container_file_name = "wav/input.wav" # message_file_name = "data/msg.txt" # output_container_file_name = "wav/output.wav" # key = 7 # recover_info_file_name = "data/recover_info.txt" # # -------------------------------------- # else: # # -------------------------------------- # input_container_file_name = "wav/output.wav" # message_file_name = "data/msg_recovered.txt" # key = 7 # recover_info_file_name = "data/recover_info.txt" # # -------------------------------------- # -------------------------------------- for opt, arg in opts: if opt == '-h': print_usage() sys.exit() elif opt in ("-i", "--ifile"): input_container_file_name = arg elif opt in ("-m", "--mfile"): message_file_name = arg elif opt in ("-o", "--ofile"): output_container_file_name = arg elif opt in ("-k", "--key"): key = int(arg) elif opt in ("-l", "--length"): message_length = int(arg) elif opt in ("-r", "--recover_info"): recover_info_file_name = arg if input_container_file_name == '' or message_file_name == '': print_usage() sys.exit() if not output_container_file_name == '': # -------------------------------------- # hide # -------------------------------------- # load settings settings = StegoSettings.Instance() settings.deserialize() if settings.validate_stream_mode(StreamMode.StreamFromFileToFile): stego_session = StegoScramblerSession( StreamMode.StreamFromFileToFile, **{ KEY_STEGO_MODE: StegoMode.Hide, KEY_INPUT_FILE_NAME: input_container_file_name, KEY_OUTPUT_FILE_NAME: output_container_file_name, StegoCore.SKIP_FRAMES_KEY: settings.frames_to_skip, StegoCore.SYNC_MARK_KEY: settings.sync_mark, StegoCore.SECURITY_OR_CAPACITY: settings.security_or_capacity }) stego_session.open_stream() stego_session.hide(message_file_name, key) else: print "There are no supported audio devices for current stream mode." # -------------------------------------- else: if message_length <= 0: message_length = gs_io.load_data_to_recover(recover_info_file_name) if message_length > 0: # -------------------------------------- # recover # -------------------------------------- # load settings settings = StegoSettings.Instance() settings.deserialize() if settings.validate_stream_mode(StreamMode.StreamFromFileToFile): stego_session = StegoScramblerSession( StreamMode.StreamFromFileToFile, **{ KEY_STEGO_MODE: StegoMode.Recover, KEY_INPUT_FILE_NAME: input_container_file_name, StegoCore.SKIP_FRAMES_KEY: settings.frames_to_skip, StegoCore.SYNC_MARK_KEY: settings.sync_mark, StegoCore.SECURITY_OR_CAPACITY: settings.security_or_capacity }) stego_session.open_stream() stego_session.scan() else: print "There are no supported audio devices for current stream mode." # -------------------------------------- else: print_usage() sys.exit() try: while stego_session.stream.is_active(): time.sleep(0.1) except KeyboardInterrupt: pass finally: if stego_session.stego_mode == StegoMode.Recover: session_key = gs_io.load_data_to_recover(recover_info_file_name) try: stego_session.recover(session_key, key, message_file_name) except AttributeError: pass except ValueError: pass except RuntimeError: pass stego_session.close_stream() print colorize('Done!', COLORS.WARNING) sys.exit(0)
def open_stream(self): # instantiate PyAudio self.p_audio = pyaudio.PyAudio() if self.stream_mode == StreamMode.StreamFromFileToFile: print colorize("Opening file stream...", COLORS.WARNING) # file to file format, channels, rate = self.p_audio.get_format_from_width(self.file_source.getsampwidth()), \ self.file_source.getnchannels(), self.file_source.getframerate() input_dev_idx = gs_device_info.detect_build_in_input_device_idx( self.p_audio) output_dev_idx = gs_device_info.detect_build_in_output_device_idx( self.p_audio) enable_input, enable_output = False, True elif self.stream_mode == StreamMode.StreamFromBuildInInputToSoundFlower: print colorize("Opening stream...", COLORS.OKBLUE) # build-in input to sound flower format, channels, rate = FORMAT, CHANNELS, RATE input_dev_idx = gs_device_info.detect_build_in_input_device_idx( self.p_audio) output_dev_idx = gs_device_info.detect_virtual_audio_device_idx( self.p_audio) enable_input, enable_output = True, True elif self.stream_mode == StreamMode.StreamFromSoundFlowerToBuildInOutput: print colorize("Opening stream...", COLORS.OKGREEN) # sound flower to build-in output format, channels, rate = FORMAT, CHANNELS, RATE input_dev_idx = gs_device_info.detect_virtual_audio_device_idx( self.p_audio) output_dev_idx = gs_device_info.detect_build_in_output_device_idx( self.p_audio) enable_input, enable_output = True, True else: print colorize("Unsupported stream mode! [%i]" % self.stream_mode, COLORS.FAIL) raise ValueError("Unsupported stream mode! [%i]" % self.stream_mode) settings = StegoSettings.Instance() print colorize("Input device: %i" % input_dev_idx, COLORS.WARNING) print colorize("Output device: %i" % output_dev_idx, COLORS.WARNING) print colorize( "Format: {0}, Channels: {1}, Rate: {2}, Frame size: {3}".format( format, channels, rate, settings.frame_size), COLORS.WARNING) # standard L-R stereo channel_map = (0, 1) try: stream_info = pyaudio.PaMacCoreStreamInfo( flags=pyaudio.PaMacCoreStreamInfo.paMacCorePlayNice, # default channel_map=channel_map) except AttributeError: print colorize( "Sorry, couldn't find PaMacCoreStreamInfo. Make sure that " "you're running on OS X.", COLORS.FAIL) sys.exit(-1) if gs_device_info.validate_audio_setup(self.p_audio, format, channels, rate, input_dev_idx): self.stream = self.p_audio.open( format=format, channels=channels, rate=rate, frames_per_buffer=settings.frame_size, input=enable_input, output=enable_output, output_host_api_specific_stream_info=stream_info, input_device_index=input_dev_idx, output_device_index=output_dev_idx, stream_callback=self.__recording_callback) self.stream.start_stream() src_latency = 1000.0 * self.stream.get_input_latency() buffer_latency = 1000.0 * settings.frame_size / rate dst_latency = 1000.0 * self.stream.get_output_latency() total_latency = buffer_latency + dst_latency + src_latency print colorize( "Expected delay: %0.1f ms (src: %0.1f, buf: %0.1f, dst: %0.1f)" % (total_latency, src_latency, buffer_latency, dst_latency), COLORS.WARNING) else: print colorize("Unsupported audio configuration!", COLORS.FAIL) raise ValueError("Unsupported audio configuration!")