https://habr.com/post/413803/- Информационная безопасность
- Python
Не так давно в моём 
учебном заведении прошёл пилотный 
Хакатон для студентов. Тематика заданий была связана с информационной безопасностью, в том числе шифрованием данных. 
 
Одним из колоритнейших заданий стал TASK-10: 
стеганография. 
Дадим определение. 
Стеганография — это способ передачи или хранения информации с учётом сохранения в тайне самого факта такой передачи (хранения).
 Иными словами, если криптография скрывает саму информацию, то стеганография скрывает факт ее передачи.
 
 
К сожалению, мы с командой не успели сделать это задание вовремя, и я решил выполнить его уже после мероприятия. 
Самым очевидным решением на тот момент казалось: 
- Перевести шифруемый текст в наборы битов. 
- Сделать тоже самое с изображением. 
- Поместить текст в случайное место изображения и сохранить как картинку.
Вот небольшой код преобразования текста в наборы битов и обратно. 
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')
 
Дальше — интереснее. Самая главная задача — придумать способ, по средством которого станет возможным шифровать сообщения. Мною был предложен 
такой способ:
- Берем символ, переводим его в число ASCII
- Создаём кортеж со случайными значениями координат
- Собираем зелёный и синий оттенки из пикселя по координатам
- Заменяем красный оттенок на номер символа по 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())
 
 код 
А теперь попробуем получить наше сообщение. 
 
 
Что и требовалось доказать, всё работает! 
Главный недостаток: видимость битых пикселей изображения в случае шифрования большого количества символов. Однако, этот недостаток отлично исправляется высоким разрешением. 
Ссылки: