Доброго времени суток, уважаемые читатели! Несколько лет я изучаю стеганографию, и считаю, что неплохо реализовал метод LSB на vb.net в своём приложении, поэтому я хочу поделится с вами моими наработками.
Для понимания некоторых терминов в статье рекомендую подробно ознакомится с теорией: LSB Стеганография. Я думаю, немногие захотят глубоко вникать в теорию, поэтому постараюсь объяснить всё максимально просто и быстро.
Q: Почему метод называется замена LSB?
A: Байт состоит из 8-ми бит, к примеру: 00001111. Видите жирным выделено 0 и 1? Самый первый в записи бит (0) принято называть MSB, а последний (1) — LSB. Поскольку последний бит минимально влияет на визуальный вид изображения, алгоритм решили назвать замена младшего бита (LSB).
Я считаю, что всё объяснил, теперь давайте перейдём к кодингу.
Допустим, мы получили массив RGB всех пикселей изображения в переменной
Dim img_bytes As Byte()
Читаем байт (для последующего изменения)
FileByte = img_bytes(fp)
Как писать информацию? Для начала надо последний бит «выставить» в ноль. Я делал это логической операцией «И».
Dim preEditByte As Byte = CByte(FileByte And 254)
После того как мы получили готовый байт нам требуется использовать логическое «ИЛИ» для записи нашей информации в переменной data.
img_bytes(fp) = CByte(preEditByte Or (data Mod 2))
Q: Почему тут
data Mod 2
A: Мы должны получить всего один бит от байта, а способа проще я не нашёл.
Q: Что за fp?
A: Я выполняю операции в цикле, а fp является текущей позицией записи (все изображения в памяти сохраняются в виде bitmap с цветовой моделью RGB. Соответственно 1 байт изображения (не метаданные) – это количество красного в пикселе, 2 байт – зелёного, 3 – синего и так далее.)
После внесения изменения требуется «подготовить» data к следующей итерации, а также
увеличить fp на единицу:
data= CByte(data 2)
fp += 1
Готовый фрагмент для записи:
For j = 1 To DataLen
data = encdata(j - 1) 'encdata as Byte() – массив с данными для записи, содержащий информацию в виде байтов
For i = 1 To 8
FileByte = img_bytes(fp) 'Dim FileByte As Byte, временная переменная
Dim preEditByte As Byte = CByte(FileByte And 254)
img_bytes(fp) = preEditByte Or (data Mod 2)
data = CByte(data 2)
fp += 1
Next i
Next j
С записью всё вроде понятно, теперь давайте разберёмся с чтением! Считываем байт
FileByte = img_bytes(FPos)
Проверяем, последний бит — 1? Если да, логическим «ИЛИ» выставляем 1, иначе оставляем 0
If (FileByte And 1) = 1 Then data = data Or bit
Если bit < 128 (2^7, поскольку даже если значение 128 сдвиг невозможен — 128 dec = 10000000 bin!!!), то делаем сдвиг влево (последний бит стает седьмым)
If bit < 128 Then bit = CByte(bit * 2)
Не забываем увеличить fp
fp += 1
И обязательно «запоминаем» информацию, которую считали, а заодно закрываем циклы
Next i
ReDim Preserve decrtext(j - 1)
decrtext(j - 1) = data
Next j
Готовый фрагмент для считывания данных:
For j = 1 To len
bit = 1
symbol = 0
For i = 1 To 8
FileByte = img_bytes(fp)
If (FileByte And 1) = 1 Then data = data Or bit
If bit < 128 Then bit = CByte(bit * 2)
fp += 1
Next i
ReDim Preserve decrtext(j - 1)
decrtext(j - 1) = data
Next j
Если вам известны более оптимизированные способы обработки данных алгоритмом замены LSB, прошу поделиться данной информацией в комментариях
Автор: рыцарь со стволом