В свете того, что тема маркировки генераций ИИ все набирает обороты, я вспомнил про такую штуку, как стеганография. Опыта с ней я не имел, только краем уха слышал на парах, когда еще был студентом, что это способ положить в фото, аудио или видео какую то информацию.
Немного полазив в интернете я понял, что стенографические методы достаточно неустойчивы, и от сильных изменений не защитят. И тут я наткнулся на статью о методе, устойчивом к повреждениям данных.
Данный метод основан на схеме Шамира, и записывает в изображение не одно зашифрованное сообщение, а несколько, что позволяет восстановить данные даже при повреждениях изображения. Ну я и решил попробовать реализовать этот метод.
Первый этап
Первый этап подразумевает различение секрета на n частей. Тут можно было схалтурить и взять готовое решение из библиотеки Crypto, что я и сделал.
def shamir_split_secret(secret: str, required_shares: int, distributed_shares: int): secret = pad(secret.encode("utf-8"), 16) return Shamir.split(k=required_shares, n=distributed_shares, secret=secret)
Разбиение представляет собой список кортежей из порядкового номера и строки байтов.
[(1, b'xfdL?xfbx08-x12gxda%xa5cxf7r?xac'), (2, b'Rx93xbeDxf3xebx99xf8PHfxe1Hxeaxd3x9b'), (3, b'xdcxb0xf2xd6xf7xcax87x93x86axcfx8exb3x94xe0;'), (4, b'xc6x7fxb9x15-Ux83ktxd89x1cMxabRb'), (5, b'H\xf5x87)tx9dx00xa2xf1x90sxb6xd5axc2')]
Второй этап
Тут определяется, есть ли вообще возможность вставить такой секрет в изображение, или же различение нужно менять, а так же вычисляется количество строк и столбцов, которые разделят изображение на блоки, в которые будут вноситься данные.
Выглядит это так:
𝑐𝑜𝑙𝑠 = 𝑐𝑒𝑖𝑙(𝑛*𝑛), 𝑟𝑜𝑤𝑠 = 𝑐𝑒𝑖𝑙 (𝑛/𝑐𝑜𝑙𝑠)
где ceil - функция, которая возвращает наименьшее целое число, не меньшее, чем аргу- мент, n - количество частей секрета
Я, конечно, реализовал все как указано в статье, но при таком подходе число строк всегда будет равняется 1, а значит мы шифруем только маленькую часть изображения. Возможно число колонок должно высчитываться иначе.
Третий этап
Третий этап самый интересный и именно на нем я не доработал. Метод, описанный в статье называется SSRC: (Share (делить), Secret (секрет), Rotation (поворот), Color (цвет))
Если первые две S уже были разобраны, остались R и C.
Начну с цвета - обычно секрет вставляют в изображение путем изменения наименьших значащих битов в одном-трех цветовых каналах r, g и b в цветовой кодировке RGB соответственно. Но любое изменение этих каналов может повлечь за собой существенные визуальные изменения пикселя. Но в данном случае изменяться будет только бит канала v в кодировке HSV. Небезосновательно полагается, что именно такой подход имеет ряд преимуществ. HSV обеспечивает хороший баланс между незаметностью изменений в изображении и высокой пропускной способностью стегоканала, а так же устойчив ко многим видам изменения изображения.
Поэтому при работе с очередным пикселем мы сначала переводим его из RGB в HSV, затем вставляем нужную нам информацию и переводим обратно в RGB.
Теперь R - поворот предлагается осуществлять на угол, кратный 90°.
При расшифровке мы последовательно будем брать блоки изображения и поворачивать их. Если этого не делать, вся информация будет содержаться только на верхней части изображения (строка то у нас одна). Но при таком подходе каждый блок будет "размазывать" информацию по картинке, на случай, если с какой то его частью что-то случится.
Расшифровка
Для расшифровки секрета необходимо иметь: изображение со встроенными данными и ключ, который содержит количество частей секрета, на которое изображение было разделено. Ключ передается в зашифрованном виде, для шифрования использовался алгоритм RSA.
Вместе с информацией о количестве частей секрета я решил передавать и число k - количество частей секрета, нужное для расшифровки исходного сообщения.
Возможно количество строк всегда равно 1 для того, чтобы получив число блоков мы всегда знали, как разбить изображение, но это решается передачей еще одного числа в зашифрованном виде.
Сделано это было для того, чтобы при извлечении частей отсеять нужное их количество, отсортировав по порядковому номеру, который также хранится вместе с байтовой частью секрета в изображении.
Изображение разбивается на блоки, а затем из них по очереди извлекаются данные.
-
Поворот -
Перевод из RGB в HSV
-
Извлечение данных.
-
При удачном восстановлении передаем сообщение пользователю.
Примечание
После знакомства со стеганографией стало понятно, что для маркировки она едва ли подойдет. Пока нет универсального способа защиты от атак на изображение, а стеганография может быть легко удалена или изменена без обнаружения, тогда как маркировка ИИ-изображений должна быть стойкой и трудно подделываемой.
Кода вышло не очень много, чуть больше 300 строк, но тащить их сюда было бы не очень уместно, как мне кажется, так что:
Автор: Aksel28