Стеганографи- ческий метод
|
Краткая характеристика метода
|
Недостатки
|
Преимущества
|
Методы сокрытия информации в аудиоконтейнерах
|
Метод сокрытия в наименьших значащих битах
|
Основан на записи сообщения в наименьшие значащие биты
исходного сигнала. В качестве контейнера используется, как правило, несжатый
аудиосигнал
|
Невысокая скрытность передачи сообщения. Низкая
устойчивость к искажениям. Используется только для определенных форматов
аудио-файлов
|
Достаточно высокая емкость контейнера (до 25 %)
|
Метод сокрытия на основе распределения по спектру
|
Основан на генерации псевдослу-чайного шума, являющегося
функцией внедряемого сообщения, и подмешивании полученного шума к основному
сигналу-контейнеру в качестве аддитивной составляющей. Кодирование потоков
информации путем рассеяния кодированных данных по спектру частот
|
Низкий коэффициент использования контейнера. Значительные
вычислительные затраты
|
Сравнительно высокая скрытность сообщения
|
Метод сокрытия на основе использования эхо-сигнала
|
Основан на использовании в качестве шумоподобного сигнала
самого аудиосигнала, задержан-ного на различные периоды времени в зависимости
от внедряемого сообщения ("дозвоночного эха")
|
Низкий коэффициент использования контейнера. Значительные
вычислительные затраты
|
Сравнительно высокая скрытность сообщения
|
Метод сокрытия в фазе сигнала
|
Основан на факте нечувствитель-ности уха человека к
абсолют-ному значению фазы гармоник. Аудио-сигнал разбивается на
последовательность сегментов, сообщение встраивается путем модификации фазы
первого сегмента
|
Малый коэффициент использования контейнера
|
Методы сокрытия информации в текстовых контейнерах
|
Метод сокрытия на основе пробелов
|
Основан на вставке пробелов в конце строчек, после знаков
препинания, между словами при выравнивании длины строк
|
Методы чувствительны к переносу текста из одного формата в
другой. Возможна потеря сообщения. Невысокая скрытность
|
Достаточно большая пропускная способность
|
Метод сокрытия на основе синтаксических особенностей текста
|
Основан на том, что правила пунктуации допускают
неоднозначности при расстановке знаков препинания
|
Очень низкая пропускная способность. Сложность
детектирования сообщения
|
Существует потенциальная возможность подобрать такой метод,
при котором потребуются весьма сложные процедуры для раскрытия сообщения
|
Метод сокрытия на основе синонимов
|
Основан на вставке информации в текст при помощи
чередования слов из какой-либо группы синонимов
|
Сложен применительно к
|
Один из наиболее
|
|
|
русскому языку в связи с большим разнообразием оттенков в
разных синонимах
|
перспективных методов. Обладает сравнительно высокой
скрытностью сообщения
|
Метод сокрытия на основе использования ошибок
|
Основан на маскировке информационных битов под естественные
ошибки, опечатки, нарушения правил написания сочетаний гласных и согласных,
замене кириллицы на аналогичные по внешнему виду латинские буквы и др.
|
Невысокая пропускная способность. Быстро вскрывается при
статистическом анализе.
|
Весьма прост в применении. Высокая скрытность при анализе
человеком
|
Метод сокрытия на основе генерации квазитекста
|
Основан на генерации текстового контейнера с использованием
набора правил построения предложений. Используется симметричная криптография
|
Невысокая пропускная способность. Бессмысленность
созданного текста
|
Скрытность определяется методами шифрования и, как правило,
весьма высока
|
Метод сокрытия на основе использования особенностей шрифта
|
Основан на вставке информации за счет изменения типа шрифта
и размера букв, а также на возможности встраивания информации в блоки с
неизвестными для браузера идентификаторами
|
Легко выявляется при преобразовании масштаба документа, при
статистическом стегоанализе
|
Высокий коэффициент использования контейнера
|
Метод сокрытия на основе использования кода документа и
файла
|
Основан на размещении информации в зарезервированных и
неиспользуемых полях переменной длины
|
Низкая скрытность при известном формате файла
|
Прост в применении
|
Метод сокрытия на основе использования жаргона
|
Основан на изменении значений слов
|
Низкая пропускная способность. Узко специализирован. Низкая
скрытность
|
Прост в применении
|
Метод сокрытия на основе использования чередования длины
слов
|
Основан на генерации текста -контейнера с формированием
слов определенной длины по известному правилу кодирования
|
Сложность формирования контейнера и сообщения
|
Достаточно высокая скрытность при анализе человеком
|
Метод сокрытия на основе использования первых букв
|
Основан на внедрении сообщения в первые буквы слов текста с
подбором слов
|
Сложность составления сообщения. Низкая скрытность
сообщения
|
Дает большую свободу выбора оператору, придумывающему
сообщение
|
Методы сокрытия информации в графических контейнерах
|
Метод сокрытия в наименьших значащих битах
|
Основан на записи сообщения в наименьшие значащие биты
исходного изображения
|
Невысокая скрытность передачи сообщения. Низкая
устойчивость к искажениям
|
Достаточно высокая емкость контейнера (до 25 %)
|
Метод сокрытия на основе модификации индексного формата
представления
|
Основан на редукции (замене) цветовой палитры и
упорядочивании цветов в пикселях с соседними номерами
|
Применяется преимущественно к сжатым изображениям.
Невысокая скрытность передачи сообщения
|
Сравнительно высокая емкость контейнера
|
Метод сокрытия на основе использования автокорреляцион-ной
функции
|
Основан на поиске с применением автокорреляционной функции
областей, содержащих сходные данные
|
Сложность расчетов
|
Устойчивость к большинству нелинейных преобразований
контейнера
|
Метод сокрытия на основе использования нелинейной модуляции
встраиваемого сообщения
|
Основан на модуляции псевдослучайного сигнала сигналом,
содержащим скрываемую информацию
|
Низкая точность детектирования. Искажения
|
Достаточно высокая скрытность сообщения
|
Метод сокрытия на основе использования знаковой модуляции
встраиваемого сообщения
|
Основан на модуляции псевдослучайного сигнала биполярным
сигналом, содержащим скрываемую информацию
|
Низкая точность детектирования. Искажения
|
Достаточно высокая скрытность сообщения
|
Метод сокрытия на основе вейвлет-преобразования
|
Основан на особенностях вейвлет-преобразований
|
Сложность расчетов
|
Высокая скрытность
|
Метод сокрытия на основе использования дискретного
косинусного преобразования
|
Основан на особенностях дискретного косинусного
преобразования
|
Высокая скрытность
|
В настоящее время существует целый ряд как коммерческих, так и бесплатных
программных продуктов, доступных обычному пользователю, реализующих известные
стеганографические методы сокрытия информации. При этом преимущественно
используются графические и аудио-контейнеры.
В нетрадиционных информационных каналах, основанных на манипуляции различных
характеристик ресурсов ИСПДн, используются для передачи данных некоторые
разделяемые ресурсы. При этом в каналах, использующих временные характеристики,
осуществляется модуляция по времени занятости разделяемого ресурса (например,
модулируя время занятости процессора, приложения могут обмениваться данными).
В каналах памяти ресурс используется как промежуточный буфер (например,
приложения могут обмениваться данными путем помещения их в имена создаваемых
файлов и директорий). В каналах баз данных и знаний используют зависимости
между данными, возникающими в реляционных базах данных и знаний.
Нетрадиционные информационные каналы могут быть сформированы на различных
уровнях функционирования ИСПДн:
· на аппаратном уровне;
· на уровне микрокодов и драйверов устройств;
· на уровне операционной системы;
· на уровне прикладного программного обеспечения;
· на уровне функционирования каналов передачи данных и линий
связи.
Эти каналы могут использоваться как для скрытой передачи скопированной
информации, так и для скрытной передачи команд на выполнение деструктивных
действий, запуска приложений и т.п.
Для реализации каналов, как правило, необходимо внедрить в
автоматизированную систему программную или программно-аппаратную закладку,
обеспечивающую формирование нетрадиционного канала.
Нетрадиционный информационный канал может существовать в системе
непрерывно или активизироваться одноразово или по заданным условиям. При этом
возможно существование обратной связи с субъектом НСД.[3]
2. Метод
сокрытия информации в наименьших значащих битах (LSB) графических контейнеров
Суть метода замена наименее значащего бита (Least Significant Bits - LSB)
заключается в сокрытии информации путем изменения последних битов изображения,
кодирующих цвет, на биты скрываемого сообщения. Разница между пустым и
заполненным контейнерами, должна быть не ощутима для органов восприятия
человека.
Принцип сокрытия информации
Рис. 2 - Преобразование текста в байтовую последовательность
Как уже описано ранее, в формате BMP изображение хранится как матрица значений оттенков
цвета для каждой точки хранимого изображения. Если каждая из компонент
пространства RGB (их еще называют каналами цвета)
хранится в одном байте, она может принимать значения от 0 до 255 включительно,
что соответствует 24-х битной глубине цвета. Особенность зрения человека
заключается в том, что оно слабо различает незначительные колебания цвета. Для
24-х битного цвета изменение в каждом из трех каналов одного наименее значимого
бита (то есть крайнего правого) приводит к изменению менее чем на 1%
интенсивности данной точки, что позволяет изменять их незаметно для глаза по
своему усмотрению.
Рассчитаем пропускную способность метода. Если отбросить в расчетах,
обычно незначительную относительно размера изображения, служебную информацию в
начале файла, то мы имеем возможность скрытно передать сообщение размером в 1/8
размера контейнера ("размазанную" по последним битам в каждом байте
матрицы цветов пикселей) или же размером в 1/4 контейнера (соответственно при
использовании 2 последних битов в байтах).
Рис. 3 - Сокрытие информации в изображении
Принцип работы стеганографического метода заключается в следующем:
Пусть, имеется 24-х битное изображение в градациях серого. Пиксел
кодируется 3 байтами, и в них расположены значения каналов RGB. Изменяя наименее значащий бит мы
меняем значение байта на единицу. Такие градации, мало того что незаметны для
человека, могут вообще не отобразиться при использовании низкокачественных
устройств вывода.
Приведенный ниже пример показывает, как сообщение может быть скрыто в
первых восьми байтах, относящихся к трем пикселей в 24-битного изображения
Pixels:
(00100111 11101001 11001000)
(00100111 11001000 11101001)
(11001000 00100111 11101001)
A:
01000001
Result:
(00100110 11101001 11001000)
(00100110 11001000 11101000)
(11001000 00100111 11101001)
В примере подчеркнуты только биты только те три бита, которые были
фактически изменены. Применение стеганографического метода LSB в среднем требует, что только
половина бит изображения-контейнера были изменены.
Небольшая модификация этой стеганографической техники позволяет
использовать для встраивания сообщения два или более младших битов на байт. Это
увеличивает объем скрытой информации в объекте-контейнере, но скрытность сильно
снижается, что облегчает обнаружение стеганографии. Другие вариации этого
метода включают в себя нивелирование статистических изменений в изображении.
Некоторые интеллектуальное программное обеспечение для выявления стеганографии
проверяет области, которые состоят из одного сплошного цвета. Для повышения
скрытности следует избежать записи изменений в эти пиксели.
Достоинства и недостатки метода
Методы LSB являются неустойчивыми ко всем видам
атак и могут быть использованы только при отсутствии шума в канале передачи
данных. Обнаружение LSB-кодированного
стего осуществляется по аномальным характеристикам распределения значений
диапазона младших битов отсчётов цифрового сигнала. [4]
3. Алгоритм и блок-схема работы программы, реализующей метод LSB в
BMP-файлах
Блок-схема функции "Schetchik"
Блок-схема
функции "Start_Click" и "Start2_Click"
Описание
блок-схемы функции "Start_Click" и "Start2_Click"
1. Начало
. Проверка выбора разрядности
. Проверка выбора каналов
4. Пересчет активного поля исходя из отступов, интервала и метода
. Исходя из режима программы выберается тип действия
.1 Чтение
.1.1 Исходя из типа данных выберается действие
.1.1.1 Текст
.1.1.1.1 Получит текст
.1.1.1.2 Удалить стопер
.1.1.1.3 Вывести текст
.1.1.2 Файл
.1.1.2.1 Получить имя файла
.1.1.2.2 Получить файл
.1.1.2.3 Удалить стоперы
.1.1.2.4 Сохранить файл
.2. Запись
.1.2 Исходя из типа данных выберается действие
.1.2.1 Текст
.1.2.1.1 Запись текста
.1.2.1.2 Запись стопера
.1.2.2 Файл
.1.2.2.1 Запись имени
.1.2.2.2 Запис стопера
.1.2.2.3 Запись файла
.1.2.2.4 Запись стопера
. Конец
Описание блок-схемы функции "Schetchik"
1. Начало
2. Инициализация переменных
. Проверка выбранных каналов
. Проверка выбранных разрядностей
6. Пересчет места необходимого под запись
. Исходя из доступного для записи места
.1 Запись возможна
.2 Запись невозможна
. Конец
Заключение
информация программа файл графический
В ходе курсового проекта были изучены базовая модель угроз персональных
данных, обрабатываемых в информационных системах персональных данных,
актуальность вопроса защиты персональных данных, метод цифровой стеганографии
LSB (Least Significant Bit, наименьший значащий бит) и возможность его
реализации на языке программирования С#. Была разработана программа реализующая
передачу мультимодальных персональных данных путем погружения в растровое
изображение произвольной разрядности. Данная программа позволяет скрыть
персональные данные и показала устойчивость к визуальным атакам.
Список
литературы
1. Федеральный закон №152-ФЗ "О персональных
данных" от 27 июля 2006 года
. http://adm-ussuriisk.ru/administration/voprosy-informatsionnoy-bezopasnosti/rukovodyaschie-dokumenty-po-zaschite-personalnyh-dannyh/bazovaya-model-ugroz-bezopasnosti-personalnyh-dannyh.htm
(дата обращения: 15.06.14)
. Базовая модель угроз безопасности персональных данных при
их обработке в информационных системах персональных данных (ФСТЭК 2008) http://fstec.ru/component/attachments/download/289 (дата обращения: 15.06.14)
. http://www.nestego.ru/2012/07/lsb.html (дата обращения:
15.06.14)
Приложение
using System; //подключение заголовочного
файлаSystem.Collections.Generic; //подключение заголовочного
файлаSystem.ComponentModel; //подключение заголовочного файлаSystem.Data;
//подключение заголовочного файлаSystem.Drawing; //подключение заголовочного
файлаSystem.Linq; //подключение заголовочного файлаSystem.Text; //подключение
заголовочного файлаSystem.Windows.Forms; //подключение заголовочного файл
namespace Program //название программы
{partial class Form1 : Form
{Form1() //инициализация компонентов
{(); //инициализация компонентов
Bitmap CryptImage, DecryptImage, image; //объявление
переменных необходимы для работы программыvysota = 0, shirina = 0; //высота и
ширина изображенияBits = 0, SendingByte = 0, InputByte = 0; // переменные для
текущего байта[] Colors = { 0, 0, 0 }, RGB = { 0, 0, 0 }; //масивы переменных
для цветового каналаtest = false; //переменная для демо-режимаsleva = 0,
//левый отступ= 0, //правый отступ= 0, //нижний отступ= 0, //вверхний отступ=
1; //интервалCryptMode = true, WriteMode = true; //переменная для режима, типа
записи и метода записи[] temp = { }, MessageBytes = { }, StopBytes1 = { 0x20,
0x20, 0x20 }, StopBytes2 = { 0x21, 0x21, 0x21 }, InputBytes = { }; //переменная
для стоперровfilesize = 0; //переменная размераMinShift1 = 0, //объявление
переменной= 0, //для записи файла,= 0, //пересчёт итогового размера поля= 0;
//для записиstr = ""; //переменная для имени файлаIndex = 0,
//переменная для записи текста= 0, //переменная размера введёного текста= 0,
//переменная размера текущего бита= 0, //переменная положения текущего бита= 0,
//цветовая позиция; //текущий битColorVAR, newColorVAR; //переменная для
представления цветовvoid Schetchik() //высчитывание допустимое кол-во кбайт для
записи
{(tabControl1.SelectedTab == tabPage1) //отключение
функции при запуске раскрытия
{BitSchetchik = 0, RGBCanal = 0, AllPixels = 0;
//переменные для пересчета максимального доступного места под запись(int i = 0;
i < 3; i++) //пересчет выбранных каналов
{(Colors[i] == 1) RGBCanal++; //
}(int j = 0; j < 8; j++) //пересчет выбранной разрядности
{(((Bits >> j) & 1) == 1) BitSchetchik++; //
}= (shirina - (sleva + sprava)) * (vysota - (sverhu +
snizu)); //пересчет максимального доступного места под запись в изображенииSize
= (AllPixels * RGBCanal * BitSchetchik) / (interval * interval); //максимальное
доступное место под запись.Text = "Допустимое количество Кбайт для записи:
" + Size / 8192 + ", " + Size % 8192 + " Кбайт";
//запись в заметку в нижнем левом углу
}toolStripStatusLabel1.Text = "Активно окно
раскрытия"; //выводит сообщение, если включен режим раскрытия
}
void Form1_Load(object sender, EventArgs e)
//приветственная заметка при запуске программы
{.Text = "Откройте изображение";
}void OpenPicture_Click(object sender, EventArgs e)
//открытие изображения, для последующего сокрытия в нём информации
{OpenImage = new OpenFileDialog(); //открывает окно для
выбора изображения.Filter = "Image Files(*.BMP)|*.BMP"; //для выбора
только bmp файлов
if (OpenImage.ShowDialog() ==
DialogResult.OK)
{ //если изображение открыто, то становятся доступными
кнопки и поля= new Bitmap(Image.FromFile(OpenImage.FileName)); //присвоение
переменной открытому изображению
pictureBox1.Image = CryptImage; //.SizeMode
= PictureBoxSizeMode.Zoom; //= CryptImage.Height; //= CryptImage.Width; //
toolStripStatusLabel1.Text = "Разрешение
изображения " + shirina + "x" + vysota; //показ размера
изобрадения в точках
Start.Enabled = true; //.Enabled = true;
//.Enabled = true; //.Enabled = true; //.Enabled = true; //.Enabled = true;
//.Enabled = true; //.Enabled = true; //
TestMode.Enabled = true; //(); //запускает процедуру на
проверку возможности записи
}
}void OpenPicture2_Click(object sender, EventArgs e)
//открытие изображения, для раскрытия информации
{OpenImage = new OpenFileDialog(); //открывает окно для
выбора изображения.Filter = "Image Files(*.BMP)|*.BMP"; //для выбора
только bmp файлов
if (OpenImage.ShowDialog() ==
DialogResult.OK)
{ //если изображение открыто, то становятся доступными
кнопки и поля= new Bitmap(Image.FromFile(OpenImage.FileName)); //присвоение
переменной открытому изображению
pictureBox2.Image = DecryptImage;
//.SizeMode = PictureBoxSizeMode.Zoom; //= DecryptImage.Height; //=
DecryptImage.Width; //
toolStripStatusLabel1.Text = "Разрешение
изображения " + shirina + "x" + vysota; //показ размера изобрадения
в точках
Start2.Enabled = true; //.Enabled = true;
//.Enabled = true; //.Enabled = true; //.Enabled = true; //.Enabled = true;
//.Enabled = true; //.Enabled = true; //.Enabled = true; //
}
}void SavePicture_Click(object sender,
EventArgs e) //сохранение изображения
{SaveImage = new SaveFileDialog(); //открывает диалоговое окно для сохранения.Filter =
"Image Files(*.BMP)|*.BMP"; //только
bmp(SaveImage.ShowDialog() == DialogResult.OK)
{ //если возможность сохранения подтверждена, то идёт
сохранение на диск
pictureBox1.Image.Save(SaveImage.FileName,
System.Drawing.Imaging.ImageFormat.Bmp);
}
}void checkBox1_CheckedChanged(object
sender, EventArgs e) //выбор разрядности
{^= 1; //выбор 1 бита, для записи единицы используем XOR
//(); //вызывает проверку на возможность записи
}void checkBox2_CheckedChanged(object
sender, EventArgs e) //выбор разрядности
{^= 2; //выбор 2 бита, для записи единицы используем
XOR(); //вызывает проверку на возможность записи
}void checkBox3_CheckedChanged(object
sender, EventArgs e) //выбор разрядности
{^= 4; //выбор 3 бита, для записи единицы используем
XOR(); //вызывает проверку на возможность записи
}void checkBox4_CheckedChanged(object
sender, EventArgs e) //выбор разрядности
{^= 8; //выбор 4 бита, для записи единицы используем
XOR(); //вызывает проверку на возможность записи
}void checkBox5_CheckedChanged(object
sender, EventArgs e) //выбор разрядности
{^= 16; //выбор 5 бита, для записи единицы используем
XOR(); //вызывает проверку на возможность записи
}void checkBox6_CheckedChanged(object
sender, EventArgs e) //выбор разрядности
{^= 32; //выбор 6 бита, для записи единицы используем
XOR(); //вызывает проверку на возможность записи
}void checkBox7_CheckedChanged(object sender,
EventArgs e) //выбор разрядности
{^= 64; //выбор 7 бита, для записи единицы используем
XOR(); //вызывает проверку на возможность записи
}void checkBox8_CheckedChanged(object
sender, EventArgs e) //выбор разрядности
{^= 128; //выбор 8 бита, для записи единицы используем
XOR(); //вызывает проверку на возможность записи
}void Horizontal_CheckedChanged(object
sender, EventArgs e) //выбор направления скрытия
{(Horizontal.Checked == true) CryptMode =
true; //выбран горизонтальныйCryptMode
= false; //выбран вертикальный
}void Reset_Click(object sender, EventArgs
e) //кнопка сброса значений сдвигов в ноль
{.Text = "0"; //.Text =
"0"; //.Text = "0"; //.Text = "0"; // = 0; //
sprava = 0; //
}void SetShift_Click(object sender,
EventArgs e) //назначение сдвигов
{//пробуем назначить
{= Convert.ToInt32(ShiftLeft.Text); //берёт числовое значение слева=
Convert.ToInt32(ShiftRight.Text); //берёт числовое значение справа=
Convert.ToInt32(ShiftBottom.Text); //берёт числовое значение снизу=
Convert.ToInt32(ShiftTop.Text); //берёт числовое значение сверху
if ((sleva + sprava) >= shirina) //если отступы по
горизонтали больше ширины изображения, то показывает ошибку и обнуляет значения
и переменные отступ справа и слева
{.Show("Сумма сдвигов по ширине превышает
разрешение изображения", "Внимание");.Text = "0";.Text
= "0";
}((sverhu + snizu) >= vysota) //если отступы по
вертикали больше высоты изображения то показывает ошибку и обнуляет значения и
переменные отступ снизу и сверху
{.Show("Сумма сдвигов по высоте превышает
разрешение изображения", "Внимание");.Text = "0";.Text
= "0";
}(); //вызывает проверку возможности записи
}//если не удалось, выдаёт ошибку
{.Show("Введены недопустимые значения, допустимы
только цифры", "Внимание");
}
}void comboBox1_SelectedIndexChanged(object
sender, EventArgs e) //назначение интервала
{= Convert.ToInt32(comboBox1.Text); //берёт из
выпадающего списка значение в интервал(); //вызывает проверку на возможность
записи
}void TextWrite_CheckedChanged(object
sender, EventArgs e) //активация/деактивация поля ввода символов
{(TextWrite.Checked == true) //если режим ввода текста
{.Visible = true; //включает текст-бокс
groupBox6.Visible = false; //делает поле невидимым=
true; //включает режим ввода текста
}//если режим записи файла
{.Visible = false; //выключает текст-бокс.Visible =
true; //делает поле видимым= false; //выключает режим ввода текста
}
}void TestMode_CheckedChanged(object sender,
EventArgs e) //тест-мод
{(TestMode.Checked == true) test = true;
else test = false; //если отмечен "Демонстративный режим", то тест-мод включён
}void OpenFile_Click(object sender,
EventArgs e) //открытие файла, для сокрытия его в bmp
{OpenFile = new OpenFileDialog(); //открывает окно для выбора файла.Filter =
"All files(*.*)|*.*"; //выбор файла любого формата(OpenFile.ShowDialog()
== DialogResult.OK)
{ //= new
System.IO.FileInfo(OpenFile.FileName).Length; //размер файла.Text = "Имя файла: "
+ OpenFile.SafeFileName; //выводит имя, расширение
FileSize.Text = "Размер файла: " + filesize /
1024 + ", " + filesize % 1024 + " Кбайт"; //показывает
максимальный размер файла, который можно записат в данное изображение
FilePath.Text = OpenFile.FileName; //путь к файлу=
OpenFile.SafeFileName; //присваивает название файла= Encoding.BigEndianUnicode.GetBytes(str);
//кодировка в юникод=
System.IO.File.ReadAllBytes(OpenFile.FileName); //присваивает все байты файла.Resize(ref
MessageBytes, MessageBytes.Length + temp.Length + 6); //добавление названия файла.Copy(StopBytes1,
0, MessageBytes, MessageBytes.Length - temp.Length - 6, 3); //добавление первого стопера
Array.Copy(temp, 0, MessageBytes,
MessageBytes.Length - temp.Length - 3, temp.Length); //добавление файла.Copy(StopBytes2,
0, MessageBytes, MessageBytes.Length - 3, 3); //добавление второго стопера
Schetchik(); //вызывает проверку на возможность записи
}
}void Start_Click(object sender, EventArgs
e) //операция сокрытие
{
if (WriteMode == true) //если режим
запись
{
if (TextBox.Text != "")
//если текст имеет символы, то
{= TextBox.Text; //присвоение переменной введенного
текста= Encoding.BigEndianUnicode.GetBytes(str); //создание массива
байт.Resize(ref MessageBytes, MessageBytes.Length + 3); //добавление введенного
текста.Copy(StopBytes2, 0, MessageBytes, MessageBytes.Length - 3, 3);
//добавление второго стопера
}{ MessageBox.Show("Нет данных для скрытия",
"Внимание"); return; } //если нет текста, то вывод ошибки
}(Bits == 0) { MessageBox.Show("Задайте
разрядность", "Внимание"); return; } //если не выбрана
разрядность выдает ошибку(Colors[0] == 0 && Colors[1] == 0 &&
Colors[2] == 0) { MessageBox.Show("Задайте цветовые каналы",
"Внимание"); return; } //если не выбраны каналы, выдает
ошибку(CryptMode == true) //если метод горизонтальный, то пересчитывает
итоговое поле для записи в изображении
{= sverhu; MaxShift1 = vysota - snizu; //=
sleva; MaxShift2 = shirina - sprava; //
}//если метод вертикальный, то пересчитывает итоговое
поле для записи в изображении
{= sleva; MaxShift1 = shirina - sprava; //=
sverhu; MaxShift2 = vysota - snizu; //
} = MessageBytes.Length; //обнуление
переменных для записи
SendingByte = MessageBytes[0]; //назначаем SendingByte первый байт
сообщения= 0; //обнуляем индекс массива сообщения= 0; //обнуляем счётчик
передаваемого бита= new Bitmap(CryptImage); //дублирование изображения для
записи
for (int y = MinShift1; y < MaxShift1
&& Index < MessageSize; y += interval) //цикл записи по вертикали(int x =
MinShift2; x < MaxShift2 && Index < MessageSize; x += interval)
//цикл записи по горизонтали
{(CryptMode == true) ColorVAR =
image.GetPixel(x,y); else ColorVAR = image.GetPixel(y, x);
RGB[0] = ColorVAR.R; //присвоение красного канала[1] =
ColorVAR.G; //присвоение зеленого канала[2] = ColorVAR.B; //присвоение синего
канала
for (ColorPosition = 0; ColorPosition < 3
&& Index < MessageSize; ColorPosition++) //перебираем цветовые каналы
{((Colors[ColorPosition] & 1) == 1) //сверяем канал
с маской цветов
{(BitPosition = 7; BitPosition >= 0;
BitPosition--) //перебираем разрядность
{ (((Bits >> BitPosition) & 1) == 1)
//сверяем разряд с маской битов
{((SendingByte & 1) == 1)
RGB[ColorPosition] |= (byte)Math.Pow(2, BitPosition);RGB[ColorPosition] &=
(byte)~(byte)Math.Pow(2, BitPosition); //для записи единицы используем ИЛИ, для записи нуля ~И
SendingBit++; //увеличиваем счётчик
переданных(SendingBit == 8) //передали байт
{(Index + 1 < MessageSize) //проверяем выход за
границы массива
{++; //увеличиваем индекс в массиве= 0; //обнуляем
счётчик битов= MessageBytes[Index]; //записываем новый байт в массив
}{ Index++; break; } //если вышли за пределы массива -
выходим из цикла
}SendingByte >>= 1; //сдвигаем передаваемый байт
на один вправо
}
}
}
}= Color.FromArgb(RGB[0], RGB[1], RGB[2]); //создаём
новый цвет(CryptMode == true) image.SetPixel(x, y, newColorVAR); else
image.SetPixel(y, x, newColorVAR); //в зависимости от метода записи,
устанавливаем новое значения компонент пикселя
}.Image = image; //устанавливаем изображение.SizeMode =
PictureBoxSizeMode.Zoom; //масштабируем изображение.Enabled = true; //включаем
кнопку "Сохранить изображение"(test == true) //если режим программы
Чтение ИЛИ выбран демонстративный режим
{.Show("Считан текст", "Внимание");
//вывод текста
DecryptImage = new Bitmap(image); //создаём копию изображения_Click(sender,
e); //
}
}void checkBox9_CheckedChanged(object
sender, EventArgs e) //выбор красного цветового канала
{[0] ^= 1; //если стоит красный, то в массиве, в 1
переменную отмечается 1(); //вызывает проверку на возможность записи
}void checkBox10_CheckedChanged(object sender,
EventArgs e) //выбор зелёного цветового канала
{[1] ^= 1; //если стоит красный, то в массиве, во 2
переменную отмечается 1(); //вызывает проверку на возможность записи
}void checkBox11_CheckedChanged(object
sender, EventArgs e) //выбор синего цветового канала
{[2] ^= 1; //если стоит красный, то в массиве, в 3
переменную отмечается 1(); //вызывает проверку на возможность записи
{(Bits == 0) { MessageBox.Show("Задайте разрядность",
"Внимание"); return; } //если не выбрана разрядность выдает
ошибку(Colors[0] == 0 && Colors[1] == 0 && Colors[2] == 0) {
MessageBox.Show("Задайте цветовые каналы", "Внимание");
return; } //если не выбраны каналы, выдает ошибку(CryptMode == true) //если
метод горизонтальный, то пересчитывает итоговое поле для записи в изображении
{= sverhu; MaxShift1 = vysota - snizu; //=
sleva; MaxShift2 = shirina - sprava; //
}//если метод вертикальный, то пересчитывает итоговое
поле для записи в изображении
{= sleva; MaxShift1 = shirina - sprava; //=
sverhu; MaxShift1 = vysota - snizu; //
}.Text = ""; //обнуляем поле текста.Resize(ref
InputBytes, 1000); //увеличиваем размер массива = 0; //обнуляем индекс массива сообщения
SendingBit = 0; //обнуляем счётчик передаваемого
бита
image = DecryptImage; //показывает
зашифрованное изображениеstop = true; //флаг остановки= ""; //для
чтения
for (int y = MinShift1; y < MaxShift1
&& stop; y += interval) //цикл записи по вертикали(int x = MinShift2;
x < MaxShift2 && stop; x += interval) //цикл записи по горизонтали
{(CryptMode == true) ColorVAR =
DecryptImage.GetPixel(x, y); else ColorVAR = DecryptImage.GetPixel(y, x);
RGB[0] = ColorVAR.R; //присвоение красного канала[1] =
ColorVAR.G; //присвоение зеленого канала[2] = ColorVAR.B; //присвоение синего
канала
for (ColorPosition = 0; ColorPosition < 3
&& stop; ColorPosition++)
{ //перебираем цветовые каналы
if ((Colors[ColorPosition] & 1) == 1)
{ //сверяем канал с маской цветов
for (BitPosition = 7; BitPosition >= 0;
BitPosition--)
{ //перебираем разрядность(((Bits >>
BitPosition) & 1) == 1)
{ //сверяем разряд с маской битов(((RGB[ColorPosition]
>> BitPosition) & 1) == 1) InputByte ^= 128;
InputBit++; //если необходимо установить единицу, делаем
XOR 128(InputBit == 8) //считали байт
{[Index] = InputByte; //записываем полученный байт(Index
+ 1 >= InputBytes.Length) Array.Resize(ref InputBytes, InputBytes.Length +
10000); //если вышли за пределы массива - увеличиваем его++; //увеличиваем индекс
в массиве= 0; //обнуляем счётчик битов= 0; //обнуляем счётчик
байтов(InputBytes[Index - 1] == 0x21 && InputBytes[Index - 2] == 0x21
&& InputBytes[Index - 3] == 0x21) //если получили стоппер
{.Resize(ref InputBytes, Index - 3); //удаляем стоппер
из полученного сообщения= false; //устанавливаем флаг остановки; //выходим из
цикла
}(WriteMode == false && InputBytes[Index - 1] ==
0x20 && InputBytes[Index - 2] == 0x20 && InputBytes[Index - 3]
== 0x20 && str == "") //если получили стоппер имени файла
{.Resize(ref InputBytes, Index - 3); //удаляем стоппер=
Encoding.BigEndianUnicode.GetString(InputBytes); //извлекаем имя и расширения файла (декодируем его в
unicode).Clear(InputBytes, 0, InputBytes.Length); //очищаем массив
Index = 0;
}
}InputByte >>= 1; //смещаем полученный байт на
один вправо
}
}
}
}
}(WriteMode == true) //если не получили имя файла,
значит принятое сообщение - текст
{= Encoding.BigEndianUnicode.GetString(InputBytes);
//декодирует сообщение в.Text = str; //unicode и вставляет в текст-бокс
}//получили файл
{SafeFile = new SaveFileDialog(); //вызываем диалог
сохранения файла.Filter = "All Files(*.*)|*.*"; //устанавливаем
фильтр диалогового окна.FileName = str; //передаём имя и расширение
файла(SafeFile.ShowDialog() == DialogResult.OK) //если пользователь нажал ОК
{
{.IO.File.WriteAllBytes(SafeFile.FileName, InputBytes);
//пробуем записать файл на компьютер
}(Exception ex)
{.Show("Не удалось сохранить файл: " +
ex.Message, "Внимание"); //если не получилось, выводим ошибку
}
}
}
}