Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Задания к лабам / 2 / itzi02 / Журнал Программист

.htm
Скачиваний:
77
Добавлен:
16.04.2013
Размер:
42.68 Кб
Скачать

Журнал "Программист"     Вышел 2-й номер журнала за 2002 год. Анонсы номера и статьи размещены на сайте.

“Программист” Подписка 2002 Агентство “Роспечать” Каталог “Газеты. Журналы. Книги. Учебные пособия. Товары.” (Россия и СНГ) Индекс: 80467

“Программист” Подписка 2002 Объединенный каталог “Почта России 2001” (Россия) Индекс: 45775

В Москве на “Программист” можно подписаться через агентство “Интер-почта”

“Интер-почта” Удобно и выгодно! Не выходя из офиса! Подписка на профессиональный журнал “Программист” В Москве и регионах. Тел. (095) 921-1138, 921-1142, 925-07-94

Вы также можете:

ЗАКАЗАТЬ любой номер журнала с доставкой по Москве Стеганография: скрытие информации Андрей Беляев

nikolsk@mail.ru

   Стеганография - очень близкая к криптографии, но все-таки независимая отрасль computer science. Ее задача - сокрытие конфиденциальной информации от посторонних глаз в самых обычных почтовых отправлениях, файлах, картинках и т.п. Сам этот термин переводится как "тайнопись".

Основные определения    Задача любой стеганографической программы - разместить исходный блок данных (стеганограмму или просто стего) в некоем вспомогательном носителе - контейнере. Контейнером может служить любой файл или поток данных. Его содержимое безразлично как отправителю, так и получателю секретного сообщения - их интересует только сама стеганограмма. Здесь важно, что любой посторонний человек, взглянув на файл-контейнер, не должен заметить ничего особенного кроме основного содержания контейнера. А значит - во-первых, сам факт отправки файла-контейнера от автора к получателю не должен выглядеть странным (зачем, скажем, пересылать по почте в другой город таблицу Менделеева?) Во-вторых, стегопреобразования должны быть настолько незаметными, чтобы даже искушенный наблюдатель не заметил в файле броских отличий от нормы.

   Немало примеров стеганографических посланий можно найти в приключенческой литературе. Так, классический двоичный сигнал "да/нет", "хорошо/плохо" - это поставленная в конце предложения точка или нарочно пропущенная запятая. При этом сам текст абсолютно никакой роли не играет - лишь бы он был осмысленным и укладывался в окружающую ситуацию. 

   Но настоящую жизнь вдохнула в стеганографию эра компьютерных технологий - появилась возможность преобразовывать сообщения молниеносно, а главное, автоматически. Сам двоичный код - уже предоставляет хороший потенциал для сокрытия данных. А уж огромное множество форматов данных и сообщений дало благодатную почву для развития этой отрасли.

   Практически все существующие стегоалгоритмы можно разбить на 4 основные категории:

1) преобразования текста;

2) метод незначащих бит; 

3) использование неотображаемых областей форматов файлов;

4) незначимое преобразование форматов файлов.

Преобразования текста    Этот класс методов является самым старым, он появился еще в "довиртуальную" эпоху и был просто перенесен на компьютеры с учетом их особенностей и возможностей. Данной категории принадлежит очень много алгоритмов. К полностью автоматическим относится, например, форматирование текста количеством пробелов отличным от единицы. Скажем, один пробел соответствует биту "0", а два - "1" (рис.1). Программа получает произвольный текст в качестве контейнера и внедряет в него какое-либо стегосообщение. Из полуавтоматических алгоритмов можно отметить метод переменной длины слов и метод первой буквы. В этих случаях работа не автоматическая; программа кодирования работает в режиме подсказки: после того как ей передали стегосообщение, она предлагает оператору начать набор текста, но накладывает на вводимые слова ограничения, несущие, собственно, информацию. 

   В методе переменной длины слова, набираемые создателем стеганограммы, должны соответствовать длине, которую укажет программа - обычно в одно слово кодируется два бита информации из стегосообщения. Например, слова длиной в 4 и 8 символов могут означать комбинацию бит "00", длиной в 5 и 9 - "01", 6 и 10 - "10", 7 и 11 букв - "11". Слова короче 4 и длиннее 11 букв можно вставлять где угодно для лексической и грамматической связки слов в предложении - программа-декодер будет просто игнорировать их (рис.2). 

   Метод первой буквы может передавать еще больше стегоинформации в одном слове: обычно это три или четыре бита. Программа-помощник в этом методе накладывает ограничение уже не на длину слова, а на первую (можно на вторую) букву. Обычно одну и ту же комбинацию могут кодировать несколько букв, например, комбинацию "101" означают слова, начинающиеся с "А", "Г" или "Т". Это дает большую свободу выбора оператору, придумывающему стегосообщение, и текст не становится нелепым (рис.3).

   Существует и множество других методов преобразования текста. В любом случае, необходимо искать золотую середину: контейнер должен быть "плотно" насыщен стегоинформацией и при этом совершенно не должен выделяться из обычной общей массы файлов такого же формата и наполнения.

Метод незначащих бит    Данный класс алгоритмов весьма интересен и широко используется на практике. Он основан на том факте, что в некоторых форматах файлов (в большинстве случаев - мультимедиа данные) младшие биты значений хотя и присутствуют в файле, но не влияют на восприятие звука или изображения человеком. Кстати, на этом же принципе основано и сжатие с потерями (JPEG, MP3, MP4 и т.п.). Именно в таких "неиспользуемых" местах в файлах можно хранить стегосообщения. Наиболее часто контейнерами служат графические форматы с прямым цветокодированием в 24 и более бит на пиксел (BMP, TIFF). Реже - звуковые файлы с абсолютным кодированием амплитуды аудиосигнала (WAV). При разумном наполнении контейнера исходный файл не отличит от заполненного без специального анализа даже опытный специалист. 

   Кстати, в цветных графических изображениях заменять младшие биты можно у каждой из составляющих (R, G, B или C, M, Y, K). И еще одно соображение: если вы предполагаете, что кто-то заподозрит в вашем файле стегосообщение - в качестве контейнера нужно выбирать не искусственно созданные картинки (стего в них обманет только неискушенного пользователя), а отсканированные фотоизображения. Только в них присутствуют шумы квантования - случайное заполнение младших бит, под которые и маскируются кусочки стегосообщения. Необходимо избегать фотографий с большими областями очень ярких и черного цветов. На таких картинках большие области в исходном файле имеют цветовые составляющие 255 и 0, соответственно и стегобайты будут характерно выделяться при просмотре файла в кодах своими 254 и 1. 

   Ниже приведена основная часть алгоритма, записывающего и считывающего стегосообщение. Контейнером служит 24-битный BMP-файл (полный текст программы и рабочий проект с примером стегосообщения можно найти на сайте журнала). В примере в каждом байте используется только 1 младший бит. Длина сообщения записывается не прямым 16-битным кодом, а в два этапа - это позволяет избежать подозрительной последовательности нулей в начале сообщения, если его длина мала. Сначала в 4 битах записывается N - "длина длины" сообщения, затем в N последующих битах собственно длина стего-сообщения в битах (старший (N+1)-ый бит считается установленным). Максимальная длина стегосообщения - 8 килобайт.

procedure AddLSBStego(const ContainerFileName:string; const Stego; BitCnt:integer);

var

Header:TBMPHeader; F:TFileStream;

Buffer:array[0..$103FF] of byte;

Ps,i,x,CntLen,BytesInLine,BytesRead:integer;

procedure AddLeastBit(Bit:integer);

begin

if Header.Width*3 <= Ps mod BytesInLine then

// перепрыгиваем выравнивание BMP-строк по границе dword

inc(Ps,BytesInLine-Header.Width*3);

Buffer[Ps]:=((Buffer[Ps]) and $FE) or (Bit and $01);

inc(Ps)

end;

begin

if (BitCnt<=$FFFF) and FileExists(ContainerFileName) then

begin

F:=TFileStream.Create(ContainerFileName,fmOpenReadWrite or fmShareExclusive);

F.Read(Header,sizeof(TBMPHeader));

if (Header.Signature=$4D42) and (Header.BMOffset=sizeof(TBMPHeader)) and (Header.ColorDepth=24) and (Header.Width*Header.Height*3>BitCnt) then

begin

BytesInLine:=(((Header.Width*3)+3) div 4)*4;

BytesRead:=F.Read(Buffer,sizeof(Buffer)); Ps:=0;

x:=BitCnt; CntLen:=0;

while x>0 do // определяем "длину длины"

begin x:=x shr 1; inc(CntLen) end;

for i:=0 to 3 do // записываем "длину длины"

AddLeastBit(CntLen shr (3-i));

for i:=0 to CntLen-2 do // записываем длину

AddLeastBit(BitCnt shr (CntLen-2-i));

for i:=0 to BitCnt-1 do // записываем саму стеганограмму

AddLeastBit(TByteArray(Stego)[i div 8] shr (7-(i mod 8)));

// возвращаемся и записываем измененный буфер на место

F.Seek(sizeof(TBMPHeader),soFromBeginning);

F.Write(Buffer,BytesRead);

end;

F.Free;

end;

end;

procedure ReadLSBStego(const ContainerFileName:string; var Stego; var BitCnt:integer);

var

Header:TBMPHeader; F:TFileStream;

Buffer:array[0..$103FF] of byte;

Ps,i,x,CntLen,BytesInLine:integer;

function ReadLeastBit:integer;

begin

if Header.Width*3 <= Ps mod BytesInLine then

// перепрыгиваем выравнивание BMP-строк по границе dword

inc(Ps,BytesInLine-Header.Width*3);

Result:=Buffer[Ps] and $01; inc(Ps)

end;

begin

if FileExists(ContainerFileName) then

begin

F:=TFileStream.Create(ContainerFileName,fmOpenRead or fmShareExclusive);

F.Read(Header,sizeof(TBMPHeader));

if (Header.Signature=$4D42) and (Header.BMOffset=sizeof(TBMPHeader)) and (Header.ColorDepth=24) then

begin

BytesInLine:=(((Header.Width*3)+3) div 4)*4;

F.Read(Buffer,sizeof(Buffer)); Ps:=0;

CntLen:=0; // определяем "длину длины"

for i:=0 to 3 do

CntLen:=(CntLen shl 1) or ReadLeastBit;

if CntLen=0 then CntLen:=16;

BitCnt:=1; // определяем длину

for i:=0 to CntLen-2 do

BitCnt:=(BitCnt shl 1) or ReadLeastBit;

x:=0; // считываем стеганограмму

for i:=0 to BitCnt-1 do

begin

x:=(x shl 1) or ReadLeastBit;

if i mod 8 = 7 then

begin TByteArray(Stego)[i div 8]:=x; x:=0 end;

end;

// "досмещение" и запись последнего неполного байта (если он был)

if BitCnt mod 8 <> 0 then

begin

x:=x shl (8-(BitCnt mod 8));

TByteArray(Stego)[BitCnt div 8]:=x;

end

end;

F.Free;

end;

end;

   Какие же есть средства обнаружения стеганограмм? Мы уже говорили о том, что изменения младших бит несложно обнаружить в очень темных и очень ярких областях картинок. Более тонкий способ - анализ спектра младших бит - как статически на некоторой области файла, так и динамически по его ходу. Подобные программы сравнивают вычисленные показания с прогнозируемыми теорией вероятности для настоящих шумов квантования в целом и для данной картинки (а значит и для данного сканера) в частности. Например, если на вход алгоритма в качестве стеганограммы подан обычный ASCII-текст сообщения, то на анализаторе спектра сразу поднимутся значения амплитуд на частотах кратных 8 по сравнению с "нормальным" пустым контейнером. Если же стегоинформация распределена не по всему файлу, а только по некоторой его части, то спектр амплитуд младших бит заполненной и незаполненной частей будет более или менее отличаться - это еще один, более тонкий, но тоже реализуемый автоматический анализ файла на стегоначинку. 

   Отсюда еще два правила для стегоалгоритмов. Во-первых, лучше подавать на вход "смешивателя" данные с хорошей статистической распределенностью. Для этого используется либо кодирование, либо полноценное шифрование (ведь результат любых стойких криптопреобразований тоже имеет очень хорошие случайные характеристики, да и отсутствие ключа у третьей стороны не даст ей возможность даже свидетельствовать о самом факте наличия стего). В качестве кодера для первого способа можно применять наложение по "исключающему ИЛИ" (XOR) исходной стеганограммы с потоком, порождаемым генератором псевдослучайных чисел приемлемой разрядности. Естественно, начальное заполнение ГПСЧ должно быть известно принимающей стороне. Кстати, сообщения можно сжимать, так мы убиваем двух зайцев: объем стего уменьшается, а его "случайность" повышается. 

   Второе правило: стегосообщение лучше распределять равномерно по всей длине контейнера. Если в контейнере слишком много "свободных" бит - можно модифицировать не все подряд, а только каждый второй или третий. С точки зрения маскировки спектральных составляющих - лучше всего вообще динамически генерировать длины подобных "прыжков", например, с помощью того же ГПСЧ - "модифицируем бит, пропускаем 1, модифицируем бит, пропускаем 4 и т.д.". 

Метод неотображаемых областей форматов файлов    Эти алгоритмы размещают стего в виде непрерывной области данных внутри известных файловых форматов. Не секрет, что многие форматы имеют зарезервированные и неиспользуемые поля и области переменной длины. Многие форматы имеют многоблочную структуру с идентификаторами типа данных, записанными в начале каждого блока.

   Программы просмотра обычно игнорируют все блоки с неизвестными им идентификаторами, что собственно нам и нужно. В качестве примера - HTML с его тегами: несуществующие теги не отображаются практически всеми браузерами. Наберите в тексте HTML-страницы <x value="торт готов"> и запустите ее на просмотр браузером…

   При своей простоте подобное стегопреобразование довольно трудно скрыть от специалиста - если вы знаете формат данного файла, то и лицо, занимающееся поиском стегосообщений тоже, скорее всего, его знает. Выход - искать редко публикуемые и сложные форматы данных и тщательно маскировать стегосообщение под общий вид файла-контейнера в этом его месте.

Метод незначимых преобразований форматов файлов    Интересный и перспективный, но довольно сложный и немногочисленный пока класс алгоритмов. Он основан на изменении структуры или содержания формата по стегозакону, но так, чтобы для программ просмотра файлов, написанных по стандартным рекомендациям, подобные изменения были бы безразличны.

   В качестве примера приведу часть программы, которая используется для изменения порядка цветов в 256-цветной палитре BMP-файла. Перестановка цветов в палитре никак не сказывается на виде файла и только с небольшой долей вероятности может быть заподозрена как стегоконтейнер. При этом она позволяет гарантированно передавать около 200 байт даже в совсем небольшой картинке. С использованием алфавитного сжатия это дает стеготекст длиной в 400 символов - например, данный абзац. Данный исходный код и проект для его тестирования также размещен на сайте журнала.

Type

TPTPStego=array[0..191] of byte;

TTransposition=array[0..255] of byte;

procedure EncodeTransposition(const Stego:TPTPStego; var TP:TTransposition);

var Src:TTransposition; i,part,bit,value,InPs,OutPs:integer;

begin

for i:=0 to 255 do Src[i]:=i;

OutPs:=0; InPs:=0;

for bit:=7 downto 1 do

for part:=0 to (1 shl bit)-1 do

begin

value:=0;

for i:=0 to bit-1 do

begin

value:=(value shl 1) or ( (Stego[InPs shr 3] shr (7-(InPs and 7))) and 1 );

inc(InPs)

end;

TP[OutPs]:=Src[value]; inc(OutPs);

move(Src[value+1],src[value],255-value)

end;

TP[254]:=Src[0]; TP[255]:=Src[1];

end;

procedure DecodeTransposition(const TP:TTransposition; var Stego:TPTPStego);

var Src:TTransposition; i,part,bit,value,InPs,OutPs:integer;

begin

for i:=0 to 255 do Src[i]:=i;

FillChar(Stego,sizeof(Stego),0);

bit:=7; part:=0; OutPs:=0;

for InPs:=0 to 253 do

begin

value:=0;

while Src[value]<>TP[InPs] do inc(value);

move(Src[value+1],src[value],255-value);

for i:=0 to bit-1 do

begin

Stego[OutPs shr 3]:=Stego[OutPs shr 3] or ( ((value shr (bit-1-i)) and 1) shl (7-(OutPs and 7)) );

inc(OutPs)

end;

inc(part);

if part=(1 shl bit) then

begin

dec(bit); part:=0

end;

end;

end;

   Эти процедуры производят только кодирование стеганограммы в перестановку из 256 элементов и обратно. В самой программе вам потребуется: 

а) при кодировании отсортировать палитру по полученному из стеганограммы закону перестановок, 

б) при декодировании определить из палитры закон ее перестановки, а затем с помощью DecodeTransposition извлечь из нее стего. 

   Не забывайте проверять перед использованием BMP-файла наличие в его палитре 256 разных (!) цветов (хотя для отсканированных фотографий, переведенных в 256-цветную палитру, это выполняется практически всегда).

Заключение    В небольшой статье невозможно рассказать обо всех существующих стегоалгоритмах. Стеганография отличается от многих областей computer science тем, что зачастую метод, придуманный самостоятельно, может успешно конкурировать с известными и распространенными схемами. Основные принципы этой отрасли: 1) скрытность превыше всего, и 2) не надо недооценивать противника.

СКАЧАТЬ ИСХОДНИК К СТАТЬЕ

В начало

Что такое программирование?

искусство

наука

ремесло

не знаю

Результаты предыдущих голосований

 обсуждение журнала/ общение с редакцией

 web-дизайн/ программи- рование

 windows программирова- ние

 unix программирование

 3D графика

 Hardware

Подпишитесь на нашу почтовую рассылку. подписаться

отписаться

125047, г. Москва, ул. Бутырский вал д.20 тел.: 250-3801 факс: 250-2121 e-mail: info@programme.ru

© ПРОГРАММИСТ 2000. Все права сохранены

Перепечатка материалов без письменного разрешения редакции запрещена.

Поддержка: mailto:webmaster@programme.ruДизайн: NETOFFICE-DESIGN u="u1162.68.spylog.com";d=document;nv=navigator;na=nv.appName;p=0;j="N"; d.cookie="b=b";c=0;bv=Math.round(parseFloat(nv.appVersion)*100); if (d.cookie) c=1;n=(na.substring(0,2)=="Mi")?0:1;rn=Math.random(); z="p="+p+"&rn="+rn+"&c="+c;if (self!=top) {fr=1;} else {fr=0;} sl="1.0"; pl="";sl="1.1";j = (navigator.javaEnabled()?"Y":"N"); sl="1.2";s=screen;px=(n==0)?s.colorDepth:s.pixelDepth; z+="&wh="+s.width+'x'+s.height+"&px="+px; sl="1.3" y="";y+=""; y+=""; y+=""; d.write(y);if(!n) { d.write("