Программирование >>  Рекурсивные объекты и фрактальные узоры 

1 ... 36 37 38 [ 39 ] 40 41 42 43


MinBX = min(c->first, MinBX); MaxBX = max(c->first, MaxBX); MinBY = min(c->second, MinBY) MaxBY = max(c->second, MaxBY)

найти крайние точки линии рисунка в пределах текущей клетки

С++;

перейти к следующей точке рисунка

если линия проходит по существенной части клетки, добавить клетку к записи if(MaxBX - MinBX + 1 > BlockW /2 11 MaxBY - MinBY + 1 > BlockH /2) Path.push back(CurBlock);

while(с != CurrentDrawing->end()); пока рисунок не кончился

в режиме записи if(Mode == RECORD)

ввести название жеста

lsRecords->Items->Strings[lsRecords->ItemIndex] =

InputBox(, Название жеста , ); записать фигуру в вектор Records Records[lsRecords->ItemIndex] = Path;

в режиме распознавания else if(Mode == RECOGNITION) {

найти в векторе Records объект, равный текущей записи (Path) for(unsigned i = 0; i < Records.size(); i++)

if(Records[i] == Path)

если объект найден, сообщить об успешном распознавании Application->MessageBox(

lsRecords->Items->Strings[i].c str(), 0);

return;

сообщить о неудаче

Application->MessageBox( Не распознано

, 0);

9.3. СТЕГАНОГРАФИЯ, ИЛИ МАСКИРОВКА НАЛИЧИЯ

ПРИСУТСТВИЯ

9.3.1. Стеганография в тексте Пересылка секретных сообщений

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

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

void fastcall TMainForm::DrawingAreaMouseUp(TObjееt *Sender,

TMouseButton Button, TShiftState Shift, int X, int Y)

выйти из режима рисования IsMouseDown = false;

определить границы (MinX, MinY, МахХ, MaxY) рисунка int MinX = min element(CurrentDrawing->begin{),

CurrentDrawing->end(), LessX)->first; int MinY = min element(CurrentDrawing->begin{),

CurrentDrawing->end(), LessY)->second; int MaxX = max elenient (CurrentDrawing->begin{) ,

CurrentDrawing->end(), LessX)->first; int MaxY = max eleinent (CurrentDrawing->begin () ,

CurrentDrawing->end(), LessY)->second; ширина и высота клеток получившейся сетки

int BlockW = (МахХ - MinX + 1) /3, BlockH = (MaxY - MinY + 1) / 3;

сжатая запись фигуры vector<pair<int, int> > Path;

vector<pair<int, int> >::iterator с = CurrentDrawing->begin()

do {

определить клетку очередной точки рисунка

pair<int, int> CurBloclc = GetBlock(*c, MinX, MaxX, MinY, MaxY)

int MaxBX = MinX, MinBX = MaxX, MaxBY = MinY. MinBY = MaxY;

пока мы находимся в той же самой клетке и рисунок не кончился

while(GetBloclc(*c, MinX, МахХ, MinY, MaxY) == CurBlock &&

с != CurrentDrawing->endО)



В режиме декодирования (команда d) из переданного на вход письма извлекается секретное сообщение и записывается в файл decoded.txt:

steganograph.exe d <файл письма>

Таким образом, функция main () вызывает в зависимости от переданной команды либо функцию кодирования, либо функцию декодирования:

int main(int argc, char* argv[]) {

if(argv[l][0] == e)

Encode(argv[2], argv[3]); else if(argv[l][0] == d)

Decode(argv[2]); return 0;

Рассмотрим сначала процесс кодирования. Необходимо предварительно вычислить длину кодируемого сообщения и выяснить, достаточен ли размер письма для его хранения. В этом нам помогут функции CountChars () и CountSpaces().

Функция CounrtChars () определяет количество символов в переданном входном файле. Мы не можем пользоваться для этой цели встроенной функцией istream: :tellg(), возвращающей длину файла в байтах, поскольку символ возврата каретки / перевода строки занимает два байта и, следовательно, для файла из нескольких строк функция tellgO будет возвращать неправильный результат.

int CountChars(char *filename) {

ifstream in(filename); int Count = 0; char c;

while(in.get(c)) пока из файла можно считать очередной символ

Count++; return Count;

Функция CountSpaces () возвращает количество пробелов (точнее, промежутков между словами, состоящих из одного или более пробельных символов) в переданном файле:

int CountSpaces(char *fname) {

количество пробелов равно количеству слов минус единица

int Spaces = -1;

string temp;

ifstream letter(fname);

ультрафиолетовыми лучами, чтобы увидеть написанное на полях, надо ещё догадаться.

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

В этой задаче предлагается спрятать сообщение внутри текстового файла.

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

в * огороде моейтётушки * растёт * огромная* редиска!

скрывает двоичное число 010001 (пробелы обозначены символами °). Таким образом, восемь пар слов позволяют закодировать один байт информации.

Итак, задача заключается в программировании системы стеганографии. Система работает в двух режимах: кодирование и декодирование.

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

В режиме декодирования на вход поступает лишь письмо с внедрёнными данными. Программа его анализирует и печатает на экране секретное сообщение.

Решение

Общая идея решения уже была описана в формулировке задачи, так что мне остаётся лишь привести реализацию с комментариями.

Программа будет работать в двух различных режимах. В режиме кодирования (команда е) текст сообщения внедряется в текст подставного письма, и результат выводится в файл encoded.txt:

steganograph.exe е <файл письма> <файл секретного сообщения>




letter s; outfile s if(c & 1)

outfile с = 1 ;

считать очередное слово письма

вывести слово с одним пробелом

если очередной бит байта с равен

единице

вывести и второй пробел

перейти к следующему биту

Значение выражения (с & 1) равно единице тогда и только тогда, когда младший бит байта с установлен; если же бит сброшен, результат операции равен нулю.

Теперь займёмся функцией Encode (),.внедряющей в текст письма длину и тело сообщения:

void Encode(char *let fn, char *rasg fn) {

количество пробелов в письме int Spaces = CountSpaces(let fn); размер сообщения int msg size = CountChars(msg fn);

считается, что длина сообщения не превышает 65535 символов и может быть закодирована двумя байтами

таким образом, количество пробелов в письме должно быть не меньше msg size * 8 (размер сообщения в битах) плюс 2*8 бит для кодирования длины if(msg size * 8 + 2 * 8 > Spaces)

{ cout Message too long endl; exit(O); }

ifstream letter(let fn), message(msg fn); ofstream outfile( encoded.txt*);

вывести старший и младший байт длины кодируемого сообщения OutByte(msg size / 256, letter, outfile); OutByte(msg size % 256, letter, outfile);

char c;

вывести сообщение while(message.get(с))

OutByte(c, letter, outfile);

в оставшемся фрагменте письма расставить пробелы случайным образом (в противном случае окончание сообщения очень хорошо заметно в закодированном файле) randomize(); string s;

вывести очередное слово, затем один или два пробела while(letter s)

outfile s (random(2) == 0 ? : );

lla этом разработка кодировщика заканчивается, можно приступать к блоку декодирования.

Алгоритм декодирования использует служебную функцию InByte () для извлечения очередного закодирова1П10го во входном файле символа:

unsigned char InByte(ifstreams letter) {

unsigned char result = 0; for(int i = 0; i < 8; i++) {

char c;

while(letter.get(c) && с !=

letter.get(c); int к = (с == ) result = 1; result 1= (12B*k);

return result;

) найти очередной пробел во входном файле считать следующий символ если считан пробел, к = 1, иначе к = О перейти к следующем/ разряду результата записать в старший бит значение к

На каждом шаге в переменную result записывается значение операции (result I 128) или (result О). Наложение нуля не меняет значения result, а наложение числа 128(двоичное 10000000) приводит к установке старшего бита.

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

while(letter temp)

Spaces++; return Spaces;

Основную работу по выводу закодированного файла выполняет функция OutByte (). Она считывает очередные восемь слов из входного файла letter, расставляет между ними пробелы в соответствии с содержимым байта с и выводит результат в выходной файл outfile:

void OutByte (unsigned char с, ifstreamSc letter, of streams outfile) {

for(int i = 0; i < 8; i++) {

string s;



1 ... 36 37 38 [ 39 ] 40 41 42 43

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика