уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Прежде, чем начнется техническая часть статьи, предлагаю Вам немного развлечься и поиграть в старую игру «Найди N-цать отличий». Вот две картинки.

Первая

Crypto_1

Вторая

001

Задание: найдите 10 различий в этих картинках :)

Собственно, даже если бы я дал Вам сравнить 2 картинки по-проще, то все-равно невооруженным глазом определить различия было бы практически невозможно.  А различаются картинки тем, что в первой записан текст, который гласит: «Привет от webdelphi.ru». Причем записан этот текст кусками по всей картинке.

Спрашивается: а нафига мне это надо?

Я не дизайнер и не художник, так что картинки мне защищать авторским правом явно не светит. Просто решил немного разобраться для себя с вопросами по работе с нетипизированными файлами. Вот и получилась небольшая программка, которая пишет в jpg-файл произвольные данные таким образом, чтобы минимально видоизменять первоначальное изображение. Где эту программу сможете использовать Вы я не имею понятия, но буду очень признателен, если Вы поделитесь со мной способами её применения.

А теперь, собственно, разберемся как эта программа действует. Во-первых JPEG как и любой другой формат файлов не является беспорядочным набором байт, а имеет чёткую спецификацию. В соответствие с которой, файл имеет свой заголовок и, в зависимости от файла один или несколько JPG-потоков, причем в файле может присутствовать: 1 поток (сама картинка) 2 потока (картинка и миниатюра), в случае 3-х потоков уже следует задуматься над тем, чтобы «почистить» картинку, т.к. обычно третьим потоком идет бесполезная инфа, записаная фотошопом и пр.

Так вот, если не нарушать заголовка, то в картинку в принципе, можно записать сколь угодно дополнительных данных. Например, моя программа действует следующим образом:

  1. Открывается файл с картинкой и из него копируется заголовок в новый файл
  2. Следом за заголовком вписывается ключ для расшифровки вписываемого текста
  3. Далее, в зависимости от потребностей, в файл с определенными промежутками вписываются части текста.
  4. Новый файл сохраняется с новым именем.

Теперь более детально, а точнее на языке Delphi. Во-первых, ключ представлен следующим образом:

type
TCryptoKey = record
  Step   : byte;//шаг записи строки
  length : word;//длина части строки для записи
  TextLength: integer; //общая длина строки
  TextParts: byte;//количество частей текста
end;

Зная ключ, можно без проблем восстановить все части текста и склеить их в первоначальный вид.

Сама процедура записи текста в картинку реализована следующим образом:

procedure PictCrypt(SourceFile, TargetFile: TFileName; CryptoKey:TCryptoKey; Text:String);
var FS, FT: File;
    i,j,part:integer;
    buf2: byte;
    doWT: boolean; //флаг разрешения записи текста
    ch:string[1];
begin
//получаем части текста для шифровки
  TextParts:=GetTextParts(Text, CryptoKey);
  doWT:=false;
  AssignFile(FS,SourceFile);
  AssignFile(FT, TargetFile);
  Reset(FS,1);
  Rewrite(FT,1);
  for I := 0 to FileSize(FS)-1 do
    begin
      if i=jpg_header+1 then
        begin
         //записываем в файл ключик
         BlockWrite(FT, CryptoKey,Sizeof(CryptoKey));
         doWT:=true;
         part:=0; //элемент массива строк с которого начать писать
        end;
      if (doWT)and ((FilePos(FT) mod CryptoKey.Step)=0)and(part<=Length(TextParts)-1)  then
       begin
         for j:=1 to Length(TextParts[part]) do
           begin
             ch:=(copy(TextParts[part],1,1));
             delete(TextParts[part],1,1);
             BlockWrite(FT, ch ,sizeof(Ch));
           end;
         part:=part+1;
       end;
      BlockRead(FS, buf2, Sizeof(buf2));
      BlockWrite(FT, buf2,Sizeof(buf2));
    end;
  CloseFile(FT);
  CloseFile(FS);
end;

После того, как текст записан в картинку, его можно прочитать обратной функцией:

function PictDeCrypt(SourceFile: TFileName):string;
var i,j,k:integer;
buf: TCryptoKey;
FS: File;
pt: string[1];
begin
  AssignFile(FS,SourceFile);
  reset(FS,1);
  for I := 0 to FileSize(FS)-1 do
    begin
     Seek(FS,jpg_header+1); //смещаемся на позицию начала ключа
     BlockRead(FS, buf,Sizeof(buf));
     CryptoKey:=buf;
     //восстанавливаем длины подстрок, записаных в файле
     LengthTextParts:=GetLengths(CryptoKey);
    end;
  for I:=FilePos(FS) to FileSize(FS)-1 do
    begin
      Seek(FS, i);
      if ((i mod CryptoKey.Step)=0) then
        begin
          if i>=jpg_header+sizeof(buf)+1 then
            begin
              for k:=0 to Length(LengthTextParts)-1 do
                begin
                  for j:=1 to LengthTextParts[k] do
                    begin
                      BlockRead(FS, pt ,Sizeof(pt));
                      Result:=Result+pt;
                    end;
      Seek(FS,FilePos(FS)+CryptoKey.Step-sizeof(pt));
    end;  
  break;
end;
end;
end;
CloseFile(FS);
end;

При этом, вначале расшифровки по известному ключу восстанавливаются длины кусков текста, записанных в картинке. Восстановление длин оcуществляется в функции:

function GetLengths(CryptoKey: TCryptoKey):TLengthTextParts;
var i:integer;
begin
//восстанавливаем длины частей текста записанных в картинку
  SetLength(Result, CryptoKey.TextParts);
  for I:=1  to CryptoKey.TextParts-1 do
    Result[i-1]:=CryptoKey.length;
    {в последнюю часть дописываем остаток}
    Result[Length(Result)-1]:=CryptoKey.length+(CryptoKey.TextLength-CryptoKey.length*CryptoKey.TextParts);
end;

Сама программа выглядит следующим образом:

screenprog

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

В итоге, после записи текста программа проверит своб работу и выведет в закладке «Техническая часть» проверяемые данные:

Если результат проверки Вас устраивает (текст читается без потерь) значит все замечательно, иначе процедуру записи следует повторить, изменив данные, например количество частей текста или размер самой строки. По предварительным данным, в картинку можно записывать до 1500 символов текста, но при этом на картинке появляется «рябь».

Так как сейчас я предоставляю Вам только наброски программы или, выражаясь более официально, бетта-версию :), то надеюсь на Ваше участие в развитии программы, указание ошибок, недочетов и пр.

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

3.7 3 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
20 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
TEMA
TEMA
14/08/2009 11:45

Помню где-то год назад попадалась мне на глаза статья с подобным алгоритмом шифрования текста, но хоть убейте не могу её отыскать в Интернете.
Есть md5,  думаю ты и так об этом знаешь)
Кстати говоря, есть программы, которые позволяют внести (записать) внутрь картинки мультемедиа файл (например музыку).

Макс
Макс
22/09/2009 11:31

Сори. Но как сохранить зашифрованную картинку? У меня не получается.

Сергей
Сергей
06/11/2009 17:23

Этот код можно использовать в виде зашиты логотипов или рекламы. Типо есть прога в ней используется файл картинки с логотипом фирмы, в файле зашифрован код. А пользователь не может взять и заменить картинку своей со своим логотипом так как в ней нет кода, и прога отказывается запускатся.  :)

Алексей
Алексей
29/10/2010 19:44

народ, берёте jpeg файл, добавляете в его конец архив (склеиваете файлы) и всё….переименовав jpg в zip — получаете архив, переименовав zip обратно в jpg — картинку…

саня
саня
07/11/2010 15:55

такой вопрос а если наобород принимать зашифрованную картинку, как текст читать??????

Сергей
Сергей
17/01/2011 00:46

А можно исходный код перекинуть(dpr+pas+dfm)?
 

TEKTON
TEKTON
20/09/2011 02:42

А если картинку редактировали, после того как в неё записан текст,  скажем в фотошопе ???
Как это отобразится на тексте ?
 
 

karton247
05/05/2012 18:47

зачем эт..

Nikolay
Nikolay
08/05/2012 23:14

Добрый день.
Подскажите, пожалуйста, в чем секрет:
при использовании программы на вашем файле все, который предложен в начале статьи все проходит идеально — картинки практически идентичны. Но при попытке использовать другие файлы того же формата JPG программа либо выдает ошибку jpeg #51 либо искажает файл достаточно значительно (от появления артефактов на изображении до превращения его в кашу из пикселей).
Написал программку перегоняющую jpg в bmp и обратно в jpg стандартными функциями Delphi, ошибка #51 больше не возникает, но проблема с искажением изображения осталась.

Vitaliy
Vitaliy
27/05/2013 14:08

кто нибудь делал это на языке С++???

bonus
bonus
04/09/2013 01:30

А проект можно целиком глянуть?

Роман
Роман
18/07/2015 02:34

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

Aqel
Aqel
28/06/2016 13:49

Что за part<= ?
В if (doWT)and ((FilePos(FT) mod CryptoKey.Step)=0)and(part<=Length(TextParts)-1) then

MoDo
MoDo
08/11/2016 18:18

Можно весть код программы?

Aqel
Aqel
20/12/2016 17:19

Вот весь бы код глянуть… :(

Yury Salom
Yury Salom
21/10/2020 23:39

Здравствуйте. Я планирую таким способом шифровать пароли. Это логично?