Хабрахабр

[Из песочницы] Python и стеганография

Не так давно в моём учебном заведении прошёл пилотный Хакатон для студентов. Тематика заданий была связана с информационной безопасностью, в том числе шифрованием данных.

Одним из колоритнейших заданий стал TASK-10: стеганография.
Дадим определение.

Стеганография — это способ передачи или хранения информации с учётом сохранения в тайне самого факта такой передачи (хранения).

Иными словами, если криптография скрывает саму информацию, то стеганография скрывает факт ее передачи.

К сожалению, мы с командой не успели сделать это задание вовремя, и я решил выполнить его уже после мероприятия.

Самым очевидным решением на тот момент казалось:

  1. Перевести шифруемый текст в наборы битов.
  2. Сделать тоже самое с изображением.
  3. Поместить текст в случайное место изображения и сохранить как картинку.

Вот небольшой код преобразования текста в наборы битов и обратно.

def text_to_binary(event): return [int(format(ord(elem),'b')) for elem in event] def binary_to_text(event): return [chr(int(str(elem),2)) for elem in event]

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

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

Прочитав немного о цветовых моделях, я решил отказаться от разложения картинки до 1 и 0 в пользу модификаций самих пикселей в RGB палитре. Для данных манипуляций мной была выбрана библиотека Pillow, вот тут неплохая статья о ней.

В изображении есть пиксели. Итак, у нас есть изображение. Пиксели образованы из основных цветов — красного, зелёного и синего.

Каждый из цветов закодирован числом от 0 до 255.

А ещё у нас есть ASCII символы, которые закодированы также.

Давайте попробуем зашифровать в эту картинку немного текста.

Картинка:

Немного текста:

C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg

Подключим необходимые библиотеки.

from PIL import Image, ImageDraw from random import randint

Затем объявим функцию и поместим в ней все объекты, которые нам пригодятся.

def stega_encrypt(): keys = [] img = Image.open(input("path to image: ")) draw = ImageDraw.Draw(img) width = img.size[0] height = img.size[1] pix = img.load() f = open('keys.txt','w')

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

  1. Берем символ, переводим его в число ASCII
  2. Создаём кортеж со случайными значениями координат
  3. Собираем зелёный и синий оттенки из пикселя по координатам
  4. Заменяем красный оттенок на номер символа по ASCII

for elem in ([ord(elem) for elem in input("text here: ")]): key = (randint(1,width-10),randint(1,height-10)) g, b = pix[key][1:3] draw.point(key, (elem,g , b)) f.write(str(key)+'\n')

Cохраняем ключи и изображение.

print('keys were written to the keys.txt file') img.save("newimage.png", "PNG") f.close()

код

Пробуем выполнить скрипт.

В результате мы получили тоже самое изображение, но в формате png и с несколькими изменёнными пикселями.

Теперь осталось всё это как-то расшифровать.

Пишем скрипт для расшифровки!

Подключаем всё, что нужно.

from PIL import Image from re import findall

Объявляем функцию для расшифровки, а также несколько объектов.

def stega_decrypt(): a = [] keys = [] img = Image.open(input("path to image: ")) pix = img.load() f = open(input('path to keys: '),'r') y = str([line.strip() for line in f])

Основной алгоритм расшифровки:

for i in range(len(findall(r'\((\d+)\,',y))): keys.append((int(findall(r'\((\d+)\,',y)[i]),int(findall(r'\,\s(\d+)\)',y)[i]))) for key in keys: a.append(pix[tuple(key)][0]) return ''.join([chr(elem) for elem in a])

Указанные регулярные выражения нужны для считывания кортежей из текстового файла.

Последнее действие — вывод на экран зашифрованного сообщения.

print("you message: ", stega_decrypt())

код

А теперь попробуем получить наше сообщение.

Что и требовалось доказать, всё работает!

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

Ссылки:

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *