Кожен із читачів напевно безліч разів бачив фільми, де супергерой/суперзлодій передавав зашифровану інформацію. Ми звикли до слова “шифр”, “шифрування” і будь-яка таємна передача інформації зараз асоціюється саме із цими словами. Хоч насправді, це далеко не так і безпечна передача інформації далеко не обмежується криптографією (шифруванням), а має ще багато методів та засобів для цього.

Зокрема, автор цього матеріалу хотів би торкнутися стеганографії. Стеганографія — це приховання самого факту передачі інформації.

Чим це принципово відрізняється від криптографії.

У випадку з криптографічними перетвореннями факт приховання інформації очевидний. Тобто, коли А передає інформацію до Б, то В знаєш, що інформація є секретна, проте не має (в кращому випадку) алгоритмів її розшифрування, якщо вона потрапить йому до рук.

Стеганографічні перетворення повідомлення дозволяють приховати від зловмисника сам факт передачі секретної інформації. Тобто, В, можливо і помітить обмін інформацією між А і Б, але не вбачатиме в ній нічого цінного.

Які переваги стеганографічного методу.

Приховання факту передачі інформації зменшує ризики того, що секретна або конфедеційна інформація потрапить до зловмисника, а навіть якщо і потрапить він може не побачити в ній нічого цінного (чому — пояснимо далі).

Це лише у фільмах секретна інформація героя забезпечена непробивним шифром. У реальному житті, зловмисник відправить до героя двох здоровезних Г. і Д., які після чергового поламаного суглоба все таки дізнаються ключ для дешифрування.

У випадку з стегоповідомленням, зловмисник навіть не матиме мотивації для таких дій, тому що стегоповідомлення не привертає до себе уваги.

Отже, як це працює?

Головний принцип стеганографії полягає у тому, щоб приховати конфеденційну інформацію всередині відкритою, як правило вседоступної інформації. Тобто один тип інформації (текст, зображення, аудіо ітд) поміщається всередину іншої інформації (текст, зображення, аудіо ітд). Таким чином контейнер (інформація, що приховує у собі стегоповідомлення) виглядає безобідно.

Найпоширенішим з методів, який читач може зустріти в Інтернеті є приховання тексту в зображенні.

Прямо у цьому матеріали ми напишемо програму, яка буде приховувати невелике повідомлення в зображенні. Будемо писати на PHP, таким чином у нас буде Web-програма.

Для початку напишемо html сторінку без зайвого дизайну (це не урок веб-дизайну все ж таки), отже файл index.php:

<meta charset=”UTF8″>
Адрес: <input type=”url” name=”url” id=”url” value=””>
Код: <input type=”text” name=”code” id=”code” value=””>
<input type=”button” value=”Приховати” >
<input type=”button” value=”Виявити” ><br>

<div id=”img_new”></div>
<br>

Думаю тут особливо пояснювати не потрібно, що в полі “Адрес” буде адреса зображення, а в полі “Код” – невелика прихована інформація. Призначення кнопок теж очевидне. У блоці img_new буде поміщатися вихідна інформація, в тому числі готовий контейнер із стегоповідомленням у ньому.

При розробці будемо використовувати фреймворк Ajax, а точніше рівну одну його функцію. Тому підключемо до index.php цей фреймворк і один наш js файл.

<script src=”ajax.js”></script>
<script src=”stego.js”></script>

Стегоалгоритми будуть відбуватися у файлах stego.php і destego.php. Зв’яжемо їх з нашим index-ом за допомогою двох функцій нашого java script: stego(), de_stego().

Отже, stego.js :

function stego (url, code) {
$(“#img_new”).html(“”);
$.ajax({
type: “POST”,
url: “stego.php”,
data: ‘url_img=’+url+’&stego_code=’+code+”,
cache: false,
success: function(html){
$(“#img_new”).html(html);
}
});
}

function de_stego (url) {
$(“#img_new”).html(“”);
$.ajax({
type: “POST”,
url: “destego.php”,
data: ‘url_img=’+url+’&stego_code=’+code+”,
cache: false,
success: function(html){
$(“#img_new”).html(html);
}
});
}

Кожна із цих функцій спочатку очищає блок img_new, потім відправляє відповідні дані із полів, які вводить користувач, на сервер, де вони далі обробляються нашою прогою. Зрештою, отримані назад дані виводить у блок img_new.

Змінюємо кнопки для того, щоб при кліку викликалися відповідні функції:

<input type=”button” value=”Приховати” onclick=”stego(document.getElementById(‘url’).value,document.getElementById(‘code’).value)”>
<input type=”button” value=”Виявити” onclick=”de_stego(document.getElementById(‘url’).value)”><br>

Тепер перейдемо до найцікавішого, до стегоперетворень. Спочатку розглянемо файл stego.php.

Найперше додамо перевірку наявності адреси зображення:

if (!$_POST[url_img]) { echo “Введіть всі дані”; exit(); }

Та перевіркутипузображення. Будемо вважати, що користувач буде використовувати лише самі поширені формати: jpg, gif, png. В іншому випадку, програма теж буде намагатися завантажити зображення, але успіх залежить від відповідної збірки PHP.

$type_img = explode (“.”, $_POST[url_img]);

switch(strtolower($type_img[count($type_img)-1])) {
case “png”: $img1 = imagecreatefrompng($_POST[url_img]); break;
case “jpg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “jpeg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “gif”: $img1 = imagecreatefromgif($_POST[url_img]); break;
default: $img1 = imagecreatefromgd ($_POST[url_img]); break;
}

Тут слід зауважити, що часто хостери не включають графічну бібліотеку GD у PHP. Якщо програма у Вас не працюватиме — зверніться із цим питання до Вашого хостер-провайдера.

Продовжимо…

Виводимо зображення користувача на екран у форматі png. Чому саме цей формат? Тому що виводити ми будемо теж у png. Так краще буде порівнювати поітм між собою зображення.

imagepng ($img1, “img/img_code1″.date(si).”.png”);
echo “Вхідне зображення: <img src=’img/img_code1″.date(si).”.png’ width=’400px’>&nbsp;&nbsp;&nbsp;&nbsp;”;

Далі визначаємо розмір зображення, задаємо початкові координати x, y, дізнаємо довжину повідомлення (обмежемо її 30 символами) та заносимо повідомлення у робочу змінну $code.

$size = getimagesize($_POST[url_img]);
$w = $size[0];
$h = $size[1];

$x = $y = 0;
$length = strlen($_POST[stego_code]); if ($length>30) {echo “Повідомлення задовге для тестової програми”}
$code = $_POST[stego_code];

Далі починаємо найцікавіше. А саме цикл, в якому наше повідомлення потрапить в зображення. Спочатку наведемо код, а далі будемо розбирати:

while ($length–) {
$color_pixel = imagecolorat ($img1, $x, $y);
$color_pixel_RGB = imagecolorsforindex ($img1, $color_pixel);
$color_pixel_RGB[blue] = ord ($code[$length]);
$color_new_pixel = imagecolorclosest ($img1, $color_pixel_RGB[red], $color_pixel_RGB[green], $color_pixel_RGB[blue]);
imagesetpixel ($img1, $x, $y, $color_new_pixel);
$x+=30; if ($x>$w) {$x=abs($x-$w); $y+=10;}

if ($y>$h) {

$color_new_pixel = imagecolorclosest ($img1, 1,

$color_pixel_RGB[green],

$color_pixel_RGB[blue]);

imagesetpixel ($img1, $x, $y, $color_new_pixel);

break 2;

}
if ($x>$w) {$x=0; $y++;}
}

Цикл буде повторюватися доки не дійдемо кінця повідомлення. До того ж будемо починати з останнього символу. Спочатку ми дізнаємося колір пікселя за координатами x,y ($color_pixel = imagecolorat ($img1, $x, $y);), заносимо в масив $color_pixel_RGB значеннявідношенян червоного, зеленого і синього кольорів у пікселі.

Прошу звернути на строчку: $color_pixel_RGB[blue] = ord ($code[$length]); – Саме тут рівень синього кольору замінюються на номер символу повідомлення в ASCII таблиці. Це є зручним, тому що вони не мають перебільшувати число 255 як і із значенням змінною відповідно RGB. Автор навмання обрав синій колір. Можете спробувати з будь-яким іншим (зеленим чи червоним кольором), які у даній програмі залишаються неторкнутими, за винятком одного випадку, про який буде далі.

Далі в циклі відбувається нанесення пікселя на нове зображення та збільшення координат. Якщо вони перевищують ширину зображення, то відбувається збільшення значення координати по висоті (y). Якщо координати y перевищують висоту, то повідомлення обривається.

Ось таким не хитрим способом ми приховали наше повідомлення у зображенні.

Але як програма при вилученні стегоповідомлення дізнається, що настав кінець повідомлення? Для цього в останньому пікселі повідомлення міняємо рівень червоного кольору на 1.

$color_new_pixel = imagecolorclosest ($img1, 1, $color_pixel_RGB[green], $color_pixel_RGB[blue]);
imagesetpixel ($img1, $x, $y, $color_new_pixel);

Та виводимо нове зображення на екран:

imagepng ($img1, “img/img_code2″.date(si).”.png”);
echo “Вихідне зображення: <img src=’img/img_code2″.date(si).”.png’ width=’400px’>”;

Таким чином файл stego.php готовий і виглядає так:
<?php
if (!$_POST[url_img]) { echo “Введіть всі дані”; exit(); }

$type_img = explode (“.”, $_POST[url_img]);

switch(strtolower($type_img[count($type_img)-1])) {
case “png”: $img1 = imagecreatefrompng($_POST[url_img]); break;
case “jpg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “jpeg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “gif”: $img1 = imagecreatefromgif($_POST[url_img]); break;
default: $img1 = imagecreatefromgd ($_POST[url_img]); break;
}

imagepng ($img1, “img/img_code1″.date(si).”.png”);
echo “Вхідне зображення: <img src=’img/img_code1″.date(si).”.png’ width=’400px’>&nbsp;&nbsp;&nbsp;&nbsp;”;
$size = getimagesize($_POST[url_img]);
$w = $size[0];
$h = $size[1];

$x = $y = 0;
$length = strlen($_POST[stego_code]); if ($length>30) {echo “Повідомлення задовге для тестової програми”}
$code = $_POST[stego_code];
while ($length–) {
$color_pixel = imagecolorat ($img1, $x, $y);
$color_pixel_RGB = imagecolorsforindex ($img1, $color_pixel);
$color_pixel_RGB[blue] = ord ($code[$length]);
$color_new_pixel = imagecolorclosest ($img1, $color_pixel_RGB[red], $color_pixel_RGB[green], $color_pixel_RGB[blue]);
imagesetpixel ($img1, $x, $y, $color_new_pixel);
$x+=30; if ($x>$w) {$x=abs($x-$w); $y+=10;}

if ($y>$h) {

$color_new_pixel = imagecolorclosest ($img1, 1, $color_pixel_RGB[green], $color_pixel_RGB[blue]);

imagesetpixel ($img1, $x, $y, $color_new_pixel);

break 2;

}
}

$color_new_pixel = imagecolorclosest ($img1, 1, $color_pixel_RGB[green], $color_pixel_RGB[blue]);
imagesetpixel ($img1, $x, $y, $color_new_pixel);

imagepng ($img1, “img/img_code2″.date(si).”.png”);
echo “Вихідне зображення: <img src=’img/img_code2″.date(si).”.png’ width=’400px’>”;
?>

Тепер перейдемо до другої функції, так як, який сенс у прихованні інформації, якщо самі потім витягнути не зможемо?

І так файл destego.php.
Половина коду аналогічний stego.php:
if (!$_POST[url_img]) { echo “Введіть всі дані”; exit(); }

$type_img = explode (“.”, $_POST[url_img]);

switch(strtolower($type_img[count($type_img)-1])) {
case “png”: $img1 = imagecreatefrompng($_POST[url_img]); break;
case “jpg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “jpeg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “gif”: $img1 = imagecreatefromgif($_POST[url_img]); break;
default: $img1 = imagecreatefromgd ($_POST[url_img]); break;
}

echo “Вхідне зображення: <img src='”.$_POST[url_img].”‘ width=’400px’>&nbsp;&nbsp;&nbsp;&nbsp;”;

echo “Код: “;

$size = getimagesize($_POST[url_img]);
$w = $size[0];
$h = $size[1];

$x = $y = 0;

Тут вже знайомі нам перевірки введення інформації, завантаження зображення та виведення його на екран

Далі йде цикл, який витягує нашу інформацію з зображення:
while ($color_pixel_RGB[red]!=1) {
$color_pixel = imagecolorat ($img1, $x, $y);
$color_pixel_RGB = imagecolorsforindex ($img1, $color_pixel);
$text = chr($color_pixel_RGB[blue]).$text;
$x+=30; if ($x>$w) {$x=abs($x-$w); $y+=10;}
if ($y>$h) { break 2; }
} ;

Цикл буде продовжуватися до тих пір, допоки не знайде позначений нами кінець повідомлення.

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

Відповідно виводимо повідомлення.

$text[0] = “”;
echo $text;

$text[0] = “” – потрібне так як перший символ залишається пустим і може бути заповнене всяким “сміттям”.

І так, destego.php виглядає так:
<?php
if (!$_POST[url_img]) { echo “Введіть всі дані”; exit(); }

$type_img = explode (“.”, $_POST[url_img]);

switch(strtolower($type_img[count($type_img)-1])) {
case “png”: $img1 = imagecreatefrompng($_POST[url_img]); break;
case “jpg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “jpeg”: $img1 = imagecreatefromjpeg($_POST[url_img]); break;
case “gif”: $img1 = imagecreatefromgif($_POST[url_img]); break;
default: $img1 = imagecreatefromgd ($_POST[url_img]); break;
}

echo “Вхідне зображення: <img src='”.$_POST[url_img].”‘ width=’400px’>&nbsp;&nbsp;&nbsp;&nbsp;”;
echo “Код: “;
$size = getimagesize($_POST[url_img]);
$w = $size[0];
$h = $size[1];

$x = $y = 0;

while ($color_pixel_RGB[red]!=1) {
$color_pixel = imagecolorat ($img1, $x, $y);
$color_pixel_RGB = imagecolorsforindex ($img1, $color_pixel);
$text = chr($color_pixel_RGB[blue]).$text;
$x+=30; if ($x>$w) {$x=abs($x-$w); $y+=10;} if ($y>$h) { break 2; }
} ;

$text[0] = “”;
echo $text;
?>

І так, наша стеганографічна програма  є і в інтернеті. Так вона виглядає:
Вводимо адресу зображення: http://technocrat.org.ua/prog/stegoua/img/img_code22528.png

Вводимо повідомлення автора матеріалу: Осадчий Сергій

Натискаємо “Приховати” і отримуємо вихідне зображення:

Зображення майже ідентичні.

Копіюємо адрес вихідного зображення, вставляємо в адресу зображення і натискаємо “Виявити”. Отримуємо:

Переконатися , що стеганографічна програма працює можете самі.

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

У наступних статтях автор розповість більше про стеганографію та інші методи захисту інформації, як при її зберігання, так і при передачі.

Осадчий Сергій

ХабраХабр

Comments are closed.