Кодирование наименее значащих бит (временная область)
Кодирование младших разрядов является простейшим способом внедрить кoнфиденциальные данные в иные структуры данных. Используя звуковой сигнал, путем замены НЗБ каждой точки осуществления выборки, представленной двоичной последовательностью, можно зашифровать значительный объем информации.
Теоретически, пропускная способность стеганоканала составляет 1 Кб/сек на 1 кГц в канале без помех, битовая скорость передачи данных составит 8 Кб/ сек в последовательности, которая оцифрована с частотой 8 кГц, и 44 Кб/сек в последовательности с частотой дискретизации 44 кГц. Платой за высокую пропускную способность канала является ощутимый на слух низкочастотный шум. Слышимость данного шума непосредственно зависит от содержимого сигнала-контейнера. Например, шум зрителей во время эфира спортивного соревнования в достаточной степени маскировал бы шум наименьших бит, модифицированных кодированием. Однако указанный шум будет ощутимым на слух при использовании в качестве контейнера аудиозаписи игры струнного квартета. Для компенсации внесенных искажений целесообразным будет использование адаптивной аттенюации данных.
Главный недостаток метода кодирования НЗБ, как и в случае с графическим контейнером, — это его слабая стойкость к посторонним воздействиям. Встроенная информация может быть разрушена из-за наличия шумов в канале, в результате передискретизации выборки и т.п., за исключением случаев, когда информация встраивалась с внесением избыточности. Однако последнее, обеспечивая приемлемую стойкость к помехам, приводит к уменьшению скорости передачи данных, зачастую на один/два порядка. На практике метод полезен только в замкнутых, полностью цифровых средах, не требующих дополнительного преобразования.
Как и в случае с использованием в качестве контейнера файла изображения, перед импортом аудиоконтейнера в документ MathCAD его необходимо подготовить в соответствующем звуковом (музыкальном) редакторе. Необходимо отметить, что программа MathCAD поддерживает только файлы WAV-формата импульсно-кодово-модулированных (ИКМ) сигналов (pulse-code modulated, PCM-signals), который, однако, является одним из самых распространенных, на сегодняшний день.
Для предотвращения возможности сравнения нарушителем перехваченного контейнера с аудиофайлами, имеющимися в его распоряжении, а на этом основании — доказывания факта существования скрытого сообщения и, возможно, извлечения или модификации последнего, в качестве контейнера рекомендуется использовать именно уникальные (созданные собственноручно) записи.
Подготовленный аудиоконтейнер следует поместить в текущую для создаваемого документа MathCAD директорию. В нашем случае предварительно был создан файл ИКМ-сигнала "C.wav".
Шаг1
Для получения информации относительно WAV-файла используется встроенная функция MathCAD GETWAVINFO("файл"), где под аргументом "файл" подразумевается текстовая строка, содержащая в себе имя файла (или же полный путь и имя файла), который предусматривается использовать в качестве контейнера.
Указанная функция возвращает четырехэлементный вектор с информацией о файле, который выступил ее аргументом. Первый элемент вектора характеризует количество каналов; второй — частоту дискретизации (в герцах); третий — количество бит, которыми кодируется один отсчет (определяющее количество уровней квантования); четвертый — среднее количество бит в секунду, которое должен обрабатывать аудиопроигрыватель, чтобы воспроизводить этот файл в реальном времени'.
Ниже приведем два возможных варианта использования данной функции:
NK=2 канала; fд=22050 Гц; Q=16 бит; B=88200 бит/с.
Шаг 2
Пользуясь полученной информацией, найдем временной вектор, отвечающий амплитудам аудиосигнала в отдельные отсчеты дискретизации. Данные амплитуды могут быть считаны с помощью функции READWAV("файл"), возвращающей массив, каждый столбец которого представляет собой отдельный канал (так, например, для моносигнала массив будет содержать только 1 столбец, для стерео — 2 и т.д.), а каждая строка массива отвечает моменту времени, который определяется номером отсчета и частотой дискретизации сигнала.
Отдельный элемент массива, в зависимости от количества бит кодирования Q, может принимать значения или от 0 до 28-1=255 (при Q = 1...8), или же от -216-1 = -32768 до 216-1-1 = 32767 (при Q = 9... 16).
Пусть С := READWAV("C.wav"). Фрагмент импортированного звука (коды отсчетов от 1000-го по 1010-й в десятичном и двоичном виде) изображен на рис.
i= | Ci,1= | Ci,2= | Ci,1= | Ci,2= | ||||
1001110111111b | 1100000001010b | |||||||
1010001011101b | 1011110110111b | |||||||
1001101010011b | 1011111101101b | |||||||
1000000100011b | 111111111000b | |||||||
110000111011b | 110011001010b | |||||||
100110001110b | 100110110101b | |||||||
11100110010b | 11001011111b | |||||||
10010010110b | 111101110b | |||||||
100110000b | 100110000b | |||||||
-953 | -1127 | -1110110010b | -10001100111b | |||||
-2466 | -3080 | -100110100010b | -110000001000b |
Рис 5.61 Фрагмент импортированного аудиофайла в виде массива квантованных амплитуд
Общее количество отсчетов на каждый из каналов: := rows(C), где rows(C) — функция, возвращающая количество строк массива С. В нашем случае, например, = 20191 отсчет на канал.
Определим временные координаты каждого из отсчетов: n:= 1 .. , tn := (сек.). Значения временных интервалов, которые отвечают приведенному выше (рис. 5.61) фрагменту отсчетов импортированного звука, приведены на рис. 5.62.
Интервал дискретизации
Следовательно, сек. Общая продолжительность звучания аудиофайла:
Очевидно, что разделив общее количество отсчетов на общую продолжительность звучания , мы получим значение частоты дискретизации
ti= |
45.351·10-3 |
45.397·10-3 |
45.442·10-3 |
45.488·10-3 |
45.533·10-3 |
45.578·10-3 |
45.624·10-3 |
45.669·10-3 |
45.714·10-3 |
45.760·10-3 |
45.805·10-3 |
Рис 5.62 Фрагмент отсчетов дискретизации импортированного аудиофайла
Владея информацией о временных координатах каждого из отсчетов и зная соответствующие этим отсчетам амплитуды (в квантованном виде), можно изобразить "осциллограмму" импортированного аудиофайла (рис. 5.63).
Рис 5.63 Временные диаграммы каналов ИКМ сигнала ”C.wav”
Шаг 3
В качестве скрываемого сообщения используем следующее:
Аналогично к тому, как это было показано выше (программные модули (М.1) и (М.2)), проведем криптографическое кодирование сообщения, результатом чего будет массив M_cod.
Шаг 4
Для скрытия одного символа сообщения достаточно 8 бит звука. Для того чтобы при извлечении скрытых данных в полученной строке символов можно было четко определить начало и конец полезного сообщения, введем соответствующие метки, которые бы тем или иным образом указывали на границы именно полезного содержания. Примем, что стартовая метка определяет порядковый номер элемента контейнера, начиная с которого в последний будут встраиваться данные. Пусть :. Метка будет сигнализировать о завершении смысловой части среди распакованных символов,
Ограничивающую метку , предварительно преобразовав ее в вектор ASCII-кодов, введем в текст закодированного сообщения:
Таким образом, общее количество символов в сообщении, которое подлежит скрытию: rows(Me)= 32 симв. Количество необходимых для этого бит (8 бит на символ): 8 rows(Me)= 256 бит.
Общее количество НЗБ аудиоконтейнера: . Следовательно, аудиофайл имеет достаточный объем и пригоден для использования в качестве контейнера для данного сообщения.
Шаг 5
Для дальнейших расчетов также будет необходимо преобразование форматов чисел из десятичного в двоичный и обратно. Для этого используем программные модули (М.102) и (М.103), которые подобны модулям (М.З) и (М.4) с той только разницей, что верхняя граница индексирования в последних (восьмерка) заменяется на rows(x)и Q соответственно. Кроме этого, при преобразовании формата аргумента учитывается его знак.
Отметим, что в модуле (М.103) знаковая функция sign(x) возвращает 0 (если х= 0); 1 (если х>0); -1 (если х<0). Это позволяет сохранить знак числа х при переводе его формата в двоичный.
Внесение бит сообщения в контейнер будем проводить с переменным шагом, величина которого будет определяться количеством единиц в двоичном значении номера элемента контейнера, который модифицировался предварительно. Для определения величины шага используем программный модуль (М.15).
Шаг 6
Для удобства дальнейших действий, проведем векторизацию массива С (в случае, если количество каналов в звуковом файле больше одного) — программный модуль (М.104), предварительно выполнив перестановку элементов каждого из столбцов в обратном порядке (с помощью функции ), что повысит степень скрытости встроенной информации.
На основе массива Cvформируем новый массив, который уже будет содержать скрытое закодированное сообщение. Для этого применим программный модуль (М.105). В модуле (М.105) каждый символ кодированного сообщения (операция цикла ) переводится в двоичный формат (переменная b), каждый разряд которого записывается вместо НЗБ числа, отвечающего значению амплитуды того или иного отсчета. При этом элементы массива Cvпроходятся не последовательно, а с переменным шагом, величина которого в данном случае обуславливается количеством единиц в двоичном представлении номера элемента, который модифицировался предварительно.
Функция step( ), входящая в состав модуля (М.15), вычислялась при значении k=20 (в этом случае должно учитываться общее количество НЗБ, которое необходимо для встраивания сообщения, и имеющееся количество элементов массива контейнера). Стартовый элемент встраивания задается меткой .
Значение элемента массива Cv, в который будет вестись запись, предварительно переводится в двоичный формат (переменная Р)). Также учитывается знак амплитуды отсчета. После проведенного изменения НЗБ модифицированное двоичное число Р переводится в формат десятичного и записывается в соответствующую позицию вектора Sv, который в начале модуля был принят равным вектору Cv.
Шаг 7
Проводим сворачивание вектора Sv в массив S, имеющий размерность первичного массива С. Одновременно выполняем обратную перестановку, возвращая элементы отсчетов на свои места:
На рис. 5.64 изображены восстановленные по соответствующим значениям амплитуд отсчетов временные диаграммы сигнала аудиоконтейнера, который содержит скрытое сообщение.
Сравнивая рис. 5.64 и рис. 5.63, можно сделать вывод об их полной визуальной идентичности, а это дает определенные основания утверждать об идентичности заполненного и исходного контейнеров на слух.
Для того чтобы убедиться в этом, необходимо записать массив S в файл, что можно сделать встроенной функцией WRITEWAV("файл", частота дискретизации, количество бит квантования):
Шаг 8
Чтобы исследовать влияние на степень скрытости того факта, в какой из разрядов числа, характеризующего уровень сигнала определенного отсчета, будет вноситься конфиденциальная информация, в модуле (М.105) в помеченной символом "*" строке вместо индекса "1" следует внести индекс, отвечающий разряду, который предполагается модифицировать.
Рис. 5.64. Временные диаграммы каналов ИКМ сигнала с модифицированными НЗБ
Среднестатистический человек не будет ощущать на слух разницы между звучанием оригинала и контейнера с сообщением, если в качестве "носителей" использовать не только самый младший, но и предыдущие несколько бит (особенно, если используется 16-битовое квантование и в аудиосигнале отсутствуют значительные участки пауз или участки с длительным постоянным уровнем звучания). Следовательно, еще одним из возможных вариантов защиты можно назвать использование изменяемой по определенному закону записи в эти несколько бит. Или же, снижая уровень скрытости, можно в несколько раз увеличить пропускную способность создаваемого аудиостеганоканала. На рис. 5.65 изображен результат внесения данных в 13-й бит числа квантованного отсчета. Нарушение скрытности очевидно.
Рис. 5.65. Временные диаграммы каналов ИКМ сигнала при внесении скрываемых данных в 13-й бит числа, характеризующего уровень сигнала
Шаг 9
Рассмотрим процесс извлечения скрытого сообщения, Для этого формируем массив значений амплитуд дискретных отсчетов, а также считываем служебную информацию из аудиоконтейнера. Полученный массив S* разворачиваем в вектор SV*, изменяя порядок элементов в столбцах (используется программный модуль (М. 104) с соответствующими заменами Cv -* Sv*, С — S*).
S*:= READWAV("S_LSB.wav");
NK = 2 канала; fД = 22050 Гц
Q = 16 бит, В = 88200 бит/сек.
Используя программный модуль (М.107), проводим извлечение скрытого кодированного сообщения.
Поскольку в подавляющем большинстве случаев получателю заранее неизвестно, сообщение какой длины было скрыто в контейнере, принимаются во внимание все элементы вектора Sv*.
Значения каждого элемента формируемого при этом вектора Мf* представляют собой коды символов предположительного сообщения, которые вычисляются в обратном к (М.105) порядке: модуль каждого младшего разряда восьмерки преобразованных в двоичный формат элементов вектора Sv*, выбранных с учетом переменного шага и известного значения метки , формирует двоичное число кода символа, формат которого в дальнейшем преобразуется в десятичный. Полученное число присваивается -му элементу вектора Mf*.
По причине вышеуказанной невозможности обработки MathCAD 12-ой версии символов, ASCII-коды которых имеют значения [0...9, 11, 12, 14...31], дополнительно вносится изменение значений 0, 1, 2….31 путем добавления к каждому из них коэффициента 32,5. Причина выбора именно такого коэффициента объяснена в комментариях к программным модулям (М.10) и (М.11).
Переменная err необходима для прерывания цикла приращения i в случае выхода аргумента Z за пределы массива SV*. Номера элементов вектора Mf* значения которых являются дробными, формируют массив N (см. модуль (МЛ ])).
Владея информацией о том, что из себя представляет конечная метка полезного сообщения (в нашем случае ) выделяем его из извлеченной последовательности, используя программный модуль (М. 108).
Вектор ASCII-кодов Mf*, предварительно преобразованный функцией vec2str( ) в соответствующую символьную строку, последовательно проходится в поиске конечной метки . Поиск осуществляется путем сравнения значения метки с выделенной частью строки символов аналогично тому, как это было реализовано в (М.12) Если совпадение произошло, параметру е присваивается значение индекса символа, завершающего содержательную часть сообщения ( ), а цикл поиска прерывается. Извлечение части строки Mf*, ограниченной символами с индексами 0 и е, проводится с помощью функции substr().
После преобразования выделенной символьной строки в вектор кодов выполняется восстановление элементов, значения которых в модуле (М. 107) были принудительно изменены на дробные.
Шаг 10
Распакованное сообщение декодируем, применяя программные модули (М.13) и (М.14). Декодированное сообщение записываем в файл.
WRITEBIN("M_dec.txt", "byte",O) = М*.
Результаты вычисления показателей визуального искажения, приведенных в главе 3 и адаптированных для оценки звукового искажения, сведены в табл. 5.6 (стр.231).