1

Тема: AHK: Шифрование текста

Сразу скажу, что я не специалист по шифрам; в примере ниже то, что придумалось на ходу. Это шифрование основано на операции XOR (Exclusive OR, исключающее ИЛИ). В AutoHotkey этот оператор обозначается как ^. Берётся код символа строки и выполняется XOR между ним и каким-то другим числом, которое является ключом шифра. Если потом выполнить XOR с тем же ключом над результатом предыдущей операции, то получим обратно исходный код символа — на этом основана дешифровка.

Если все символы строки сксорить с одним и тем же ключом, то разгадать такой шифр будет несложно, т.к. чисел размером в байт (возможных ключей) — всего 256. Отсюда возникла идея варьировать ключ — а именно брать в качестве такового по очереди коды символов некоторой ключевой фразы. Дальнейшее усложнение — повторная обработка полученного шифра другими фразами, чтобы каждый символ текста оказался сксорен с комбинацией ключей.

Если код символа текста совпадёт с кодом ключа, то результатом XOR будет 0. Оставлять 0 в строке нельзя, т.к. это затруднит впоследствии разбор этой строки командой Loop, Parse. Так что в этом случае код символа оставляется без изменения.

Функция Cipher требует по крайней мере одну ключевую фразу, остальные две необязательны. Если фраз больше одной, то при расшифровке их нужно передавать функции в обратном порядке по сравнению с тем, какой был при шифровке.

Text =
(
Не жалею, не зову, не плачу,
Все пройдет, как с белых яблонь дым.
Увяданья золотом охваченный,
Я не буду больше молодым.

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

Key1 = AutoHotkey forever!
Key2 = Хрен поймёшь, что тут написано.
Key3 = 1234567890
                           
Shifr := Cipher(Text, Key1, Key2, Key3)  ; Шифруем.

MsgBox, % Shifr

Text := Cipher(Shifr, Key3, Key2, Key1) ; Дешифруем, ключи в обратном порядке.

MsgBox, % Text


; =============== Функция шифровки/дешифровки ====================

Cipher(Src, Key1, Key2 = 0, Key3 = 0)  ; Два последних ключа необязательны.
{
  Loop, 3
  {
    If not Key%A_Index%
      Break
    StringSplit, Keys, Key%A_Index%  ; Разбиваем фразу на отдельные ключи.
    Dest =
    Loop, Parse, Src  ; Перебор символов текста.
    {
      Index := Mod(A_Index, Keys0) + 1  ; Чтобы Index не вышел за пределы
                                        ; числа символов в ключевой фразе.
      Key := Asc(Keys%Index%)   ; Очередной ключ.
      Code := Asc(A_LoopField)  ; Код очередного символа текста.
      Dest .= Chr(Code = Key ? Code : Code ^ Key) ; Шифруем и добавляем.
    }
    Src := Dest
  }
  Return Dest
}

2 (изменено: YMP, 2012-08-27 08:44:15)

Re: AHK: Шифрование текста

Несколько замечаний, вытекающих из обсуждения в этой теме.

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

; Два ключа.
Shifr := Cipher(Text, Key1, Key2) ; Шифровка.
Text := Cipher(Shifr, Key2, Key1) ; Дешифровка.

; Один ключ.
Shifr := Cipher(Text, Key1) ; Шифровка.
Text := Cipher(Shifr, Key1) ; Дешифровка.

Во-вторых, на что влияет число ключей и их длина. Стойкость к расшифровке максимальна, если длина исходного текста не превышает длину ключа. В примере выше длины ключей составляют 19, 31 и 10 символов. Поскольку ключи используются совместно, накладываясь друг на друга, это эквивалентно использованию единственного ключа длиной 19*31*10 = 5890 символов (эквивалентно при условии, что потенциальному взломщику неизвестен способ шифрования, т.к. на перебор всех вариантов трёх коротких ключей требуется меньше времени, чем получаемого из них длинного).

Эта эквивалентная длина вычисляется как наименьшее общее кратное, т.е. самое малое из чисел, которые делятся без остатка на все три длины. В данном случае все длины взаимно простые (не делятся нацело друг на друга), поэтому наименьшее общее кратное равно произведению длин. Но если бы длины составляли, например, 16, 8 и 4 символа, наименьшее общее кратное было бы всего 16.