Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Шифрование данных


Автор: Vit 16.4.2002, 23:25
Пример шифрования данных на Дельфи :D :D :D :D

Код

procedure DoEncode(var Source:String; const Key:string);
asm
 Push  ESI
 Push  EDI
 Push  EBX
 Or    EAX,EAX
 Jz    @Done
 Push  EAX
 Push  EDX
 Call  UniqueString
 Pop   EDX
 Pop   EAX
 Mov   EDI,[EAX]
 Or    EDI,EDI
 Jz    @Done
 Mov   ECX,[EDI-4]
 Jecxz @Done
 Mov   ESI,EDX
 Or    ESI,ESI
 Jz    @Done
 Mov   EDX,[ESI-4]
 Dec   EDX
 Js    @Done
 Mov   EBX,EDX
 Mov   AH,DL
 Cld
@L1:
 Test  AH,8
 Jnz   @L3
 Xor   AH,1
@L3:
 Not   AH
 Ror   AH,1
 Mov   AL,[ESI+EBX]
 Xor   AL,AH
 Xor   AL,[EDI]
 Stosb
 Dec   EBX
 Jns   @L2
 Mov   EBX,EDX
@L2:
 Dec   ECX
 Jnz   @L1
@Done:
 Pop   EBX
 Pop   EDI
 Pop   ESI
end;

Автор: Chingachguk 17.4.2002, 01:05
Мне кажется, у этого алгоритма есть два недостатка:

1) Код, сильно зависимый от компилятора. Далеко не всегда
регистр EAX будет указывать на ячейку с адресом Source,
а регистр EDX - на пароль(Key). Но это мелочь.

2) Единственный байт гаммы(или ксорирующей последовательности),
который меняется при шифровании - это длина пароля. Остальные
символы пароля НИКАК НЕ ПЕРЕМЕШИВАЮТСЯ в ходе шифрования. Алгоритм
шифрования примерно такой:

 Len:=Lengh(Key);
 Index:=Lengh(Key)-1;
 i:=1;
 repeat
   Len:=func1(Len);
   Source[i]:=(Key[Index] xor Len) xor Source[i];
   dec(Index);
   if Index:=0 then Index:=Lengh(Key)-1;
 until i<Lenght(Source);

Нетрудно видеть, что основной для тупого подбора является
длина пароля. Пусть она равна 10. Очевидно, что 1-ый,11,21..
символы будут зашифрованы ОДИНАКОВЫМ значением Key[Index],
но разными значениями Len. Казалось бы, Len для 1,11,21...
будет разным, но это ерунда - ведь Len вычисляется однозначно
на ЛЮБОМ шаге через реккурентный закон func1 !

И это - фатальный недостаток.

Автор: Vit 17.4.2002, 02:49
Спасибо, Chingachguk, именно это я хотел бы и услышать. Естественно это код не мой - я в асемблере совсем не очень, но я его нашел где-то, уже не помню где, и использую совместно с контрольной суммой - т.е. примерно это выглядит как:

1. Вычисляется контрольная сумма
2. Контрольная сумма дописывается к данным
3. Все это шифруется этим алгоритмом
{по условиям задачи мне нужны в зашифрованном виде только латинские буквы и цифры, никаких спец-символов отсюда следующий шаг}
4.  Массив я разбиваю по 5 бит, каждая комбинация из 5ти битв имеет значение "Большие латинские буквы+Малые латинские буквы+цифры+пара знаков"

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

Ты не мог бы подумать как исправить/дополнить алгоритм для улучшения  степени защиты? Мне это в общем не обязательно - здесь у меня защита от чайника, чтоб просто предупредить изменение в ручную некоторых параметров, собственно для внутреннего пользования, так что о настоящей защите от взлома речь не идет, но может кому надобна и более суровая защита.

Автор: Chingachguk 17.4.2002, 13:17
Вообще-то лучше использовать известные алгоритмы шифрования. Это не только мое мнение, самое главное - таких людей, как Крис Касперски ;)

Я не особо разбираюсь в этой области. Лично могу порекомендовать RC4 - он прост, легко реализуется(не более экрана на Паскале), быстр. Разумеется, есть более современные и улучшенные алгоритмы - ну там DES или что-то в этом духе.

А как улучшить данный алгоритм - так надо ПЕРЕМЕШИВАТЬ ВСЕ символы пароля в ходе шифрования. Необходимо, чтобы КАЖДЫЙ символ пароля по возможности участвовал в зашифровке каждого символа шифруемой последовательности. Тогда число вариантов для перебора резко увеличится.

Автор: Over G 17.4.2002, 13:37
А вы не скажите, как потом шифрованный текст или ещё что РАШИФРОВАТЬ?

Автор: Chingachguk 17.4.2002, 13:44
Каким именно алгоритмом зашифрованный ? Стандартные ведут себя так:

Зашифрованный текст = RC4(текст, пароль);

Расшифрованный текст = текст = RC4(Зашифрованный текст, пароль);

Одна и та же функция ! ;)

Автор: Vit 17.4.2002, 14:23
А где его взять этот RC4? Может можешь на форум бросить процедурку?

Автор: Chingachguk 17.4.2002, 15:35
Вот ниже отрывок из моей статьи по защите файлов в Excel. Статья была не совсем на тему RC4 и я не спец, так что извините, если что не так:

Цитата

...
Что же такое RC4, MD5 и тому подобные штучки? Схематично их алгоритмы можно представить таким образом — шифруемая информация (последовательность битов) должна быть, с одной стороны, скрыта во множестве “мусора” (тривиальный пример — сложение каждого байта строки с байтами строки-константы), а с другой стороны — рассеяна по полученному множеству таким образом, чтобы связи между шифруемыми битами были потеряны, но не окончательно — ведь еще предстоит проверка (например, меняем четные байты пароля на нечетные).
Возьмем, к примеру, алгоритм шифрования RC4. Он состоит из подготовительной части и самого шифрования.
Пусть у нас есть пароль “Password”.  Формируем две таблицы длиной 256 байтов. Первая (S-таблица) будет вначале содержать числа 0, 1, 2, …, 255, а вторую (K-таблицу) заполним паролем примерно так:

K = “PasswordPassword...”

(пароль ведь может быть меньше 256 байтов). После этого введем индексы i и j, j вначале равен 0. Выполним 256 замен между таблицами:

i = 0,1.. 255, j = (j + S[i] + K[i]) and 255,  xchg S[i],S[j].

Полученная таблица S называется таблицей подстановок.
Теперь пусть есть некоторая информация, которую надо зашифровать — массив байтов  Info[0,1,2…]. Определим два счетчика Q1 и Q2 с начальными значениями 0. При шифрации каждого байта Info[] выполняем следующие действия:

Q1 = (Q1 + 1) and 255, Q2 = (Q2 + S[Q2]) and 255,
xchg S[Q1], S[Q2], T = (S[Q1] + S[Q2]) and 255,
Gamma = S[T],
и,  наконец — вот оно:
Info[..] = Info[..] xor Gamma.

Таким образом, мы формируем таблицу подстановок S и с ее помощью проводим операции “исключающее  ИЛИ” (xor) над элементами шифруемой информации.  Как уже было сказано ранее, четное число операций xor над байтом дает исходный байт. Поэтому достаточно провести еще раз ту же самую операцию над зашифрованным алгоритмом RC4 массивом Info[], чтобы получить исходный Info[].

Автор: neutrino 18.4.2002, 10:03
Кто нибудь может ответить на такой вопрос. На сколько хорош следуюший алгоритм шифровки:
 1) пользуясь определенным методом мешаем таблицу текстових символов (их всего 224)
 2) исходный текст воспримем как число в 225-ричной системе счисления и используя перемешанную таблицу (скажем на первом месте - символ $, значит это нуль и.т.д.) переведем это число в 224-х ричную систему счисления. За 225 возьмем какои-нить символ, который в тексте встретиться не может (например код ESCAPE)

Как этот шифр можно взломать? Спасибо.

Автор: Chingachguk 18.4.2002, 11:55
Цитата

neutrino Дата сообщения: 18.4.2002,11:03...
На сколько хорош следуюший алгоритм шифровки:
1) пользуясь определенным методом мешаем таблицу текстових символов (их всего 224)
2) исходный текст воспримем как число в 225-ричной системе счисления и используя перемешанную таблицу (скажем на первом месте - символ $, значит это нуль и.т.д.) переведем это число в 224-х ричную систему счисления. За 225 возьмем какои-нить символ, который в тексте встретиться не может (например код ESCAPE)

Как этот шифр можно взломать? Спасибо.


Очень плох.
(На мой взгляд !;)

Насколько я понял, речь идет о табличной замене. Пусть Alpha[1..224] - таблица перемешанных симолов, Text[1..N] - шифруемая последовательность. Если я правильно понимаю, алгоритм шифровки i-ого символа сведется к:

 CurrChar:=Text[i];
 for j:=1 to 224 do
   begin
      if CurrChar=Alpha[j] then break;
   end;
 Text[i]:=Alpha[j];

Ну или что-то в этом роде. Я правильно понял ?

1) Если я знаю таблицу замены, те Alpha, то ЛЮБОЙ зашифрованный этим алгоритмом текст прозрачен;
2) Если я не знаю таблицу, но знаю способ шифрования.
 Тогда взломщик может поступить так. Предположим, это - английский текст. Тогда в нем почти наверняка встретятся такие сочетания, как "the", "is"...
Как преобразуется "the" ? Очень просто:
 
  t -> Alpha[k1]; h -> Alpha[k2]; e -> Alpha[k3];

Т.е. полагаем неизвестными эти три Alpha[k1..3]; Далее ПЕРЕБОРОМ этих трех неизвестных (всего не более 254 x 254 x 254 вариантов) делаем обратную расшифровку текста. Например, предполагая на очередном шаге:

  Alpha[k1..3] = "a","b","c";

Делаем замену в шифруемом тексте:

   "a" -> "t", "b" -> "h", "c" -> "e",

И анализируем такой текст. Если мы видим в нем эти самые "the", то мы ПОДОБРАЛИ три символа из таблицы замены(с некоторой вероятностью, конечно, но есть и другие сочетания)...

Автор: neutrino 18.4.2002, 12:39
Нет, ты не правильно меня понял. Ты не должен заменять какие-то буквы на другие в тексте. Надо перемешать как бы сами цыфры. Например, примем, что в десятичной системе не будет (по возростанию) цифр в таком порядке: 0123456789, а допустим: 0594837261. Теперь тебе надо зашифровать текст: "938", ты берешь всю эту строку и думаешь, что она в 11-ричной (в этом примере) системе счисления. и переводишь ее в 10-ричную (10 пускай будет - "#", он не встречается в исходном тексте):  
твои новые цыфры:

0 - 0
1 - 5
2 - 9
3 - 4
4 - 8
5 - 3
6 - 7
7 - 2
8 - 6
9 - 1

теперь, у тебя есть текст: "938", ты знаешь, что, например 9 - это 1, 3-4 и 8-6. значит эта строка равна 146 (в 11-ричной системе) и ты ее переводишь в 10-ричную: (146=1*11^2+4*11^1+6*11^0=171)
Ну конечно с десятиричной системой плохой пример :) Так у нас получилось: "171" - это зашифрованный вариант текста "938". Вот и все. Теперь если ты знаешь таблицу цифр по которой мы зашифровивали (0594837261), то расшифровать будет очень просто, если ты знаешь какая цифра кокое значение имеет.
Это все конечно применимо только к текстовым данным.

Автор: Chingachguk 18.4.2002, 14:15
Все равно не понял до конца ! ;)

И чем это отличается от табличной замены ? ;)

Ты это имел в виду:

Пусть есть 224 символа: a,b,c... = Alpha0[1..224];
Сначала перемешиваем Alpha0 -> Alpha[1..224];
Выполняем табличную замену символов шифруемого текста по Alpha;

А дальше ?!...

Автор: neutrino 18.4.2002, 15:08
Нет. Короче я тебе в приват напишу поподробнее. То что этот метод работает (шифрует и расшифровывает) это точно. Мне было бы очень интересно знать как его можно взломать. Если тебя не затруднит конечно. Пиво не поставлю, но спасибо скажу :) СПАСИБО.

Автор: Chingachguk 18.4.2002, 16:01
О'кей !

Можно даже так сделать:

Ты высылаешь мне:

- зашифрованный текст;
- алгоритм шифрования;

Я не знаю:

- исходного текста;
- ключа шифрования(таблицу замен или что там еще);

И я пытаюсь открыть его. Если я это сделаю, то алгоритм не очень ...
Неплохо было бы, если в исходном тексте будут русские буквы, то хотелось бы, чтоб они были в виндовой кодировке>...

ЗЫ А почему вдруг речь зашла о пиве ? ;)

Автор: neutrino 18.4.2002, 16:24
Поверь мне, я не капельки не сомневаюсь в твоем проффесионализме, ибо я помню как ты "сделал" программу етого, помнишь, "Кто взломает мой шифр, тому пиво!" (кстати про пиво я отсюда взял). И совсем не претендую на то чтобы этим алгоритмом пользовались в КГБ, ФБР, Мосаде или еше где нибудь. Я просто хотел узнать твоего мнения. Я могу послать тебе зашифрованний текст (но не большой, мне самому будет очень трудно его вручную зашифровать), но что ты имеешь ввиду под словом алгоритм? Программу? У меня ее нет. Все на чистом листе бумаги. Я тебе могу послать описание алгоритма (идею). Так ты согласен? Если да кинь мне сообшение в приват форума. Я тебе очень благодарен за отзыв. До этого никто не брался разбирать мой алгоритм.

Автор: Lence 5.8.2006, 17:38
Цитата

А где его взять этот RC4? Может можешь на форум бросить процедурку? 


Пользуюсь вот этим ... 

Код

procedure TMainForm.RC4ButtonClick(Sender: TObject);
var f:file;
    size,i:integer;
    buf:array of byte;
begin
  if OpenDialog.Execute then begin
    MainForm.Cursor:=crHourGlass;
    RC4Init(KeyEdit.Text);
    assignfile(f,OpenDialog.FileName);
    reset(f,1);
    size:=filesize(f);
    ProgressBar.Show;
    ProgressBar.Position:=0;
    ProgressBar.Max:=size;
    reset(f,size);
    setlength(buf,size);
    blockread(f,buf[0],1);
    closefile(f);

    for i:=0 to (size-1) do begin
      buf[i]:=RC4GetCryptoByte(buf[i]); //!!!
      Application.ProcessMessages;
      ProgressBar.StepIt;
    end;

    rewrite(f,size);
    blockwrite(f,buf[0],1);
    closefile(f);
    finalize(buf);
    KeyEdit.Text:='';
    RC4Button.Enabled:=false;
    MD5Label.Caption:='';

    MainForm.Cursor:=crDefault;
  end;
end;

function IntToHexFix(a:LongWord):string;
var b,r:string[8];
begin
  b:=IntToHex(a,8);
  SetLength(r,8);

  r[7]:=b[1];
  r[8]:=b[2];

  r[5]:=b[3];
  r[6]:=b[4];

  r[3]:=b[5];
  r[4]:=b[6];

  r[1]:=b[7];
  r[2]:=b[8];

  Result:=r;
end;


в общем я там снизу прикрутил исходники - посмотрите - разберетесь :-)

здесь в опен диалог выбираете файл для шифрования и в Edit1 пишете пароль ... и все - шифруется - так же и обратно .... 

а вот сама паска - заталкайте ее рядышком ... 

Код

unit crypto;
{---------------------------}
interface

type TArr16xLongword=array [0..15] of Longword;

procedure RC4Init(key:shortstring);
function RC4GetCryptoByte(ch:byte):byte;
procedure MD5Init;
procedure MD5Do(M:TArr16xLongword);
procedure MD5Finalize(var a,b,c,d:Longword);
function ROL(c:Longword;n:byte):Longword;
{---------------------------}
implementation
var rc4i,rc4j:byte;
    rc4s:array[0..255] of byte;

    md5a,md5b,md5c,md5d:Longword;

procedure RC4Init(key:shortstring);
var k:array[0..255] of byte; //вспомогательный массив
    i,j,t:byte;
begin
  //обнуляем глобальные счётчики
  rc4i:=0;
  rc4j:=0;

  //заполняем основной массив линейно
  for i:=0 to 255 do rc4s[i]:=i;

  //заполняем вспомогательный массив ключом
  //при этом он должен заполнить весь массив
  //для этого повторяем его нужное число раз
  j:=0;
  t:=length(key);
  for i:=0 to 255 do begin
    inc(j);
    k[i]:=Byte(key[j]);
    if j=t then j:=0;
  end;

  //заполняем основной массив в зависимости от ключа
  j:=0;
  for i:=0 to 255 do begin
    j:=(j+k[i]+rc4s[i]) mod 256;

    //меняем местами rc4s[i] и rc4s[j]
    t:=rc4s[i];
    rc4s[i]:=rc4s[j];
    rc4s[j]:=t;
  end;
end;
{---------------------------}
function RC4GetCryptoByte(ch:byte):byte;
var t:byte;
begin
  rc4i:=(rc4i+1) mod 256; //циклически увеличиваем счётчик на единицу
  rc4j:=(rc4j+rc4s[rc4i]) mod 256;
  
  //меняем местами rc4s[rc4i] и rc4s[rc4j]
  t:=rc4s[rc4i];
  rc4s[rc4i]:=rc4s[rc4j];
  rc4s[rc4j]:=t;
  
  t:=(rc4s[rc4i]+rc4s[rc4j]) mod 256; //получаем номер байта в массиве для шифрования
  RC4GetCryptoByte:=rc4s[t] xor ch; //получаем шифрованный байт
end;
{---------------------------}
procedure MD5Init;
begin
  md5a:=$67452301;
  md5b:=$efcdab89;
  md5c:=$98badcfe;
  md5d:=$10325476;
end;
{---------------------------}
function ROL(c:Longword;n:byte):Longword;assembler;
asm
 mov eax,c
 mov cl,n
 rol eax,cl
end;
{---------------------------}
procedure MD5Do(M:TArr16xLongword);
var a,b,c,d:Longword;// Временные переменные

procedure FF(var a,b,c,d,m:Longword;s:byte;t:Longword);
begin
  a:=b+(rol((a+((b and c)or((not b) and d))+m+t),s));
end;

procedure GG(var a,b,c,d,m:Longword;s:byte;t:Longword);
begin
  a:=b+(rol((a+((b and d)or(c and (not d)))+m+t),s));
end;

procedure HH(var a,b,c,d,m:Longword;s:byte;t:Longword);
begin
  a:=b+(rol((a+(b xor c xor d)+m+t),s));
end;

procedure II(var a,b,c,d,m:Longword;s:byte;t:Longword);
begin
  a:=b+(rol((a+(c xor (b or(not d)))+m+t),s));
end;

begin //MD5Do
 // копируем во временные переменные
  a:=md5a;
  b:=md5b;
  c:=md5c;
  d:=md5d;

  //Этап 1
  FF(a,b,c,d, M[0], 7,$D76AA478);
  FF(d,a,b,c, M[1],12,$E8C7B756);
  FF(c,d,a,b, M[2],17,$242070DB);
  FF(b,c,d,a, M[3],22,$C1BDCEEE);

  FF(a,b,c,d, M[4], 7,$F57C0FAF);
  FF(d,a,b,c, M[5],12,$4787C62A);
  FF(c,d,a,b, M[6],17,$A8304613);
  FF(b,c,d,a, M[7],22,$FD469501);

  FF(a,b,c,d, M[8], 7,$698098D8);
  FF(d,a,b,c, M[9],12,$8B44F7AF);
  FF(c,d,a,b,M[10],17,$FFFF5BB1);
  FF(b,c,d,a,M[11],22,$895CD7BE);

  FF(a,b,c,d,M[12], 7,$6B901122);
  FF(d,a,b,c,M[13],12,$FD987193);
  FF(c,d,a,b,M[14],17,$A679438E);
  FF(b,c,d,a,M[15],22,$49B40821);

  //Этап 2
  GG(a,b,c,d, M[1], 5,$F61E2562);
  GG(d,a,b,c, M[6], 9,$C040B340);
  GG(c,d,a,b,M[11],14,$265E5A51);
  GG(b,c,d,a, M[0],20,$E9B6C7AA);

  GG(a,b,c,d, M[5], 5,$D62F105D);
  GG(d,a,b,c,M[10], 9,$02441453);
  GG(c,d,a,b,M[15],14,$D8A1E681);
  GG(b,c,d,a, M[4],20,$E7D3FBC8);

  GG(a,b,c,d, M[9], 5,$21E1CDE6);
  GG(d,a,b,c,M[14], 9,$C33707D6);
  GG(c,d,a,b, M[3],14,$F4D50D87);
  GG(b,c,d,a, M[8],20,$455A14ED);

  GG(a,b,c,d,M[13], 5,$A9E3E905);
  GG(d,a,b,c, M[2], 9,$FCEFA3F8);
  GG(c,d,a,b, M[7],14,$676F02D9);
  GG(b,c,d,a,M[12],20,$8D2A4C8A);

  //Этап 3
  HH(a,b,c,d, M[5], 4,$FFFA3942);
  HH(d,a,b,c, M[8],11,$8771F681);
  HH(c,d,a,b,M[11],16,$6D9D6122);
  HH(b,c,d,a,M[14],23,$FDE5380C);

  HH(a,b,c,d, M[1], 4,$A4BEEA44);
  HH(d,a,b,c, M[4],11,$4BDECFA9);
  HH(c,d,a,b, M[7],16,$F6BB4B60);
  HH(b,c,d,a,M[10],23,$BEBFBC70);

  HH(a,b,c,d,M[13], 4,$289B7EC6);
  HH(d,a,b,c, M[0],11,$EAA127FA);
  HH(c,d,a,b, M[3],16,$D4EF3085);
  HH(b,c,d,a, M[6],23,$04881D05);

  HH(a,b,c,d, M[9], 4,$D9D4D039);
  HH(d,a,b,c,M[12],11,$E6DB99E5);
  HH(c,d,a,b,M[15],16,$1FA27CF8);
  HH(b,c,d,a, M[2],23,$C4AC5665);

  //Этап 4
  II(a,b,c,d, M[0], 6,$F4292244);
  II(d,a,b,c, M[7],10,$432AFF97);
  II(c,d,a,b,M[14],15,$AB9423A7);
  II(b,c,d,a, M[5],21,$FC93A039);

  II(a,b,c,d,M[12], 6,$655B59C3);
  II(d,a,b,c, M[3],10,$8F0CCC92);
  II(c,d,a,b,M[10],15,$FFEFF47D);
  II(b,c,d,a, M[1],21,$85845DD1);

  II(a,b,c,d, M[8], 6,$6FA87E4F);
  II(d,a,b,c,M[15],10,$FE2CE6E0);
  II(c,d,a,b, M[6],15,$A3014314);
  II(b,c,d,a,M[13],21,$4E0811A1);

  II(a,b,c,d, M[4], 6,$F7537E82);
  II(d,a,b,c,M[11],10,$BD3AF235);
  II(c,d,a,b, M[2],15,$2AD7D2BB);
  II(b,c,d,a, M[9],21,$EB86D391);

  // увеличиваем значение переменных
  inc(md5a,a);
  inc(md5b,b);
  inc(md5c,c);
  inc(md5d,d);
end;
{---------------------------}
procedure MD5Finalize(var a,b,c,d:Longword);
begin
  a:=md5a;
  b:=md5b;
  c:=md5c;
  d:=md5d;
end;

end.


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)