1

Тема: AHK: Поразрядная ротация

Всем доброго времени суток!
У меня вопрос: возможно ли реализовать на AHK поразрядную (побитовую) ротацию содержимого переменой типа Char (число от 0 до 255 включительно)?
Нужно сделать нечто похожее на команду RRCA или RLCA из ассемблера для Z80 (к сожалению, других, более "современных" примеров не знаю).
Схема такая:
http://zxpress.ru/chapters_images/asminf/image015.gif
Пример ротации влево:
(шаг --> двоичное значение = десятичное значение)
0 --> 00001010 = 10 (начальное значение)
1 --> 00010100 = 20
2 --> 00101000 = 40
3 --> 01010000 = 80
4 --> 10100000 = 160
5 --> 01000001 = 65
6 --> 10000010 = 130
7 --> 00000101 = 5
8 --> 00001010 = 10 (вернулись к первоначальному значению)

Или, быть может, есть какая-то "внешняя" функция, которую можно вызвать из AHK и получить на выходе нужный результат?

2

Re: AHK: Поразрядная ротация

Позвольте около предметный вопрос
Какова сфера применения возможности описанной вами выше? — Для чего планируете использовать?

3 (изменено: YMP, 2012-08-23 17:52:15)

Re: AHK: Поразрядная ротация

KepocuH пишет:

Или, быть может, есть какая-то "внешняя" функция, которую можно вызвать из AHK и получить на выходе нужный результат?

Сейчас заглянул в msvcrt.dll — там есть функция _rotl, но она вращает int, а не char.
Можно записать нужные ассемблерные инструкции в память и потом вызывать этот код как функцию через DllCall.

4

Re: AHK: Поразрядная ротация

creature.ws пишет:

Для чего планируете использовать?

Наткнулся на форуме на эту тему, и от нечего делать стал размышлять, чего бы еще в этот скрипт можно было бы добавить...

Пока додумался вот до чего:


bin = 189	; первоначальное значение
mov = 8	; количество шагов ротации
#r::
    MsgBox % RRC(bin, mov)
return
 
#l::
    MsgBox % RLC(bin, mov)
return
 
RLC(byte, step) ;Ротация влево
{
    ret =
    loop %step%
	{
        byte *= 2
        byte > 255 ? byte -= 255 : byte
        ret = %ret%%byte%`n
    }
    return % ret
}
RRC(byte, step) ;Ротация вправо
{
    ret =
    loop %step% 
	{
        byte := byte / 2
        round(byte) <> Floor(byte) ? byte := Floor(byte)+128 : byte := round(byte)
        ret = %ret%%byte%`n
    }
    return % ret
}

Может быть, можно как-то оптимизировать скрипт?

5 (изменено: Irbis, 2012-08-23 19:47:06)

Re: AHK: Поразрядная ротация

; RLC
byte := mod(byte << 1, 256) | (byte >> 7)
; RRC
byte := 128*(byte & 1) | (byte >> 1)

Кстати, приведенный код не соответствует схеме из #1 - крайний бит при вращении не поступает во флаг С.

Немного переделанный вариант с демонстрацией ротации (8 - максимальное число для сдвига):

bin = 189    ; первоначальное значение
mov = 8    ; количество шагов ротации
#1::
   ans =
   loop % mov
      ans .= RRC(bin, A_Index) "`n"
   MsgBox % ans
return
 
#2::
   ans =
   loop % mov
      ans .= RLC(bin, A_Index) "`n"
   MsgBox % ans
return
 
RLC(byte, step)
{
   return % mod(byte << step, 256) | (byte >> (8-step))
}

RRC(byte, step)
{
   return % mod(byte << (8-step), 256) | (byte >> step)
}

6 (изменено: Александр_, 2012-08-24 14:52:28)

Re: AHK: Поразрядная ротация

не знаю что там за флаг, но циклический сдвиг "испокон веков" делали так: ((x<<n)|(x>>(8-n)))&255. Это сдвиг влево на n<=8 битов для восьмибитного числа, сдвиг влево по аналогии, код легко обобщается на произвольные n и на числа любой разрядности(ограничения всем ясны, я надеюсь).

7

Re: AHK: Поразрядная ротация

Да, вариант с &255 удобней (и быстрей работает, конечно), но я уже "изобрел велосипед" с mod(a,b)

8 (изменено: Александр_, 2012-09-03 18:53:26)

Re: AHK: Поразрядная ротация

Irbis пишет:

Да, вариант с &255 удобней (и быстрей работает, конечно), но я уже "изобрел велосипед" с mod(a,b)

Это всё есть в книге "Алгоритмические трюки для программистов", если не знакомы, то рекомендую.

9

Re: AHK: Поразрядная ротация

Спасибо, забрал, обязательно проштудирую.

10

Re: AHK: Поразрядная ротация

Александр_ пишет:

((x<<n)|(x>>(8-n)))&255. Это сдвиг вправо

По-моему, это как раз влево.

11

Re: AHK: Поразрядная ротация

Всем спасибо! В итоге скрипт стал выглядеть так:


bin = 10
mov = 1
C =
 
#1::
    bin := RLC(bin, mov)
    MsgBox %bin% %C%
return
#2::
    bin := RRC(bin, mov)
    MsgBox  %bin% %C%
return

RRC(byte, step)
{
    global C := (byte>>(step-1))&1
    return % ((byte>>step)|(byte<<(8-step)))&255
}
RLC(byte, step)
{
   global C := (byte>>(8-step))&1
   return % ((byte<<step)|(byte>>(8-step)))&255
}

Добавил переменную-флаг С, в которую попадает крайний бит при ротации.

12 (изменено: Irbis, 2012-08-24 11:50:35)

Re: AHK: Поразрядная ротация

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

13

Re: AHK: Поразрядная ротация

Irbis пишет:

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

Смотря от кого вам надо шифроваться. Например, вы лично смогли бы расшифровать?

14

Re: AHK: Поразрядная ротация

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

15

Re: AHK: Поразрядная ротация

Irbis пишет:

Все упирается как обычно, в пропорцию риск/вознаграждение, т.е. в данном случае потраченное_время/профит.

Ну так иначе это разговор о сферическом коне в вакууме. Пистолет, к примеру, игрушка против танка, но против человека — смертельное оружие.

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

Жаль, что вы не хотите "поставить задачу". Интересный был бы эксперимент.

16 (изменено: Irbis, 2012-08-24 14:25:01)

Re: AHK: Поразрядная ротация

Данный в коллекции пример, конечно, интересен - но стойкость его определяется лишь наличием 3 ключей (ключевых фраз) общей длинной (в примере) 60 символов, дающих период повтора заXORивающей последовательности 5890 символов. На практике пользователи для защиты информации применяют один ключ (ака пароль). А он в своей массе чуть менее, чем полностью длиной от 5 до 10 символов - значит и период заксоривания защищаемого текста будет таким же. То есть в случае криптоанализа атака будет идти не на ключ, а состоять из анализа зашифрованного текста. И тут техника достаточно отработана, материла на эту тему хватает. При длинне текста >> длины ключа период повтора находится быстро, дальше перебор вкупе с семантическим анализом... (Не брутфорс )

   Могу предложить для усиления стойкости приведенного алгоритма, хотя бы в случае одного ключа, использовать его как начальное значения для псевдослучайного генератора некой строки (последовательности символов), и XORить защищаемый текст с этой строкой - стойкость к взлому в данном случае возрастет намного больше, чем просто при увеличении числа ключей. То есть, если при простом цикле сложность взлома с увеличеним длины ключа растет слабо (При длинне текста >> длины ключа), то при генерации строки сложность растет в геометрической прогрессии, и тут скорее всего, брутфорс будет единственным решением.

YMP пишет:

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

Согласен, но ведь и информация бывает разной. Если, к примеру, младший брат-школьник поковыряет текстовый файл, где "спрятаны" ваши логин/пароль от сетевой игрушки, скорее всего, он махнет рукой на это дело. А если злой хакер сольет (ну, всякое бывает) зашифрованный файл с паролями от платежных систем и данными электронных кошельков - это будет совсем другая, печальная песня...

17

Re: AHK: Поразрядная ротация

Т.е. фактически длина ключа в моём примере 5890? И если текст будет короче, то расшифровать не так-то просто?

Насчёт генерации псевдослучайной строки, к сожалению, не имею представления, что это такое и как делается. По мне, так проще 3 ключа придумать. Или даже 4 — четверостишие какое-нибудь, чтобы не забыть.

18

Re: AHK: Поразрядная ротация

Исходя из современных требований к криптосистемам, алгоритм шифрования должен быть таков, чтобы, даже зная его (но не зная ключ), расшифровать данные за обозримый промежуток времени не представлялось возможным. И алгоритмы, обсуждаемые нами здесь, этому условию не удовлетворяют. Но в подавляющем большинстве случаев "для домашнего использования" подходят. Спрятать от жены переписку с любовницей, от мамы - пикантные фото с вечеринки в стрип-баре, от босса... ну, еще что-нибудь - для этого вполне годится скриптик, делающий что-то вроде {x:=x^255} с каждым байтом данных.

Irbis пишет:

А если злой хакер сольет (ну, всякое бывает) зашифрованный файл с паролями от платежных систем и данными электронных кошельков

Как вариант, могу предложить использовать для ХОРки ключ такой же длины, как сам файл. А если после этого сделать еще несколько перестановок символов, вставить в "случайные" места избыточный код, поиграться с битами, можно запутать товарища хакера настолько, что даже брут не поможет!
Главное - хранить шифратор отдельно от данных...

19

Re: AHK: Поразрядная ротация

При длине случайного ключа равной длине шифруемого текста при должной сохранности ключа иных методов шифрования не требуется.

20

Re: AHK: Поразрядная ротация

Длина ключа в данном случае - это НОК для длин всех 3х ключей, т.е. 19*31*10, так как они взаимно простые.
Если бы длины ключей были 16, 8 и 4, то длина результирующего ключа была бы всего 16 символов.

Генерировать строку строку можно так, хотя ОЧЕНЬ не рекомендуется использовать встроенные функции генерации случайных чисел - лучше использовать свои :

Key = мой пароль
len := 200
MsgBox % RandString(Key, len)
return

RandString(Key, len)
{
   Init := 1
   StringSplit, Chars, Key
   loop % Chars0
     Init := (Init*Asc(Chars%A_Index%)+7)&0xFFFFFFFF
   res =
   Random,,Init  
   loop % len
   {
      Random, rand, 1, 255
	  res .= Chr(rand)
   }
   return % res
}

21 (изменено: Александр_, 2012-08-24 15:44:15)

Re: AHK: Поразрядная ротация

YMP пишет:

По-моему, это как раз влево.

Влево конечно, поправил свой пост.
Что касается того метода шифрования- он плох по ряду причин. Во-первых, время- там три прохода по тексту, хотя нужен всего один. Во-вторых, криптостойкость резко упадёт если просто известен способ шифрования, не говоря уже про случаи когда известен один из паролей. В-третьих, если текст закодировать, а потом декодировать, то мы можем и не получить исходный текст, а значит прикрутить хэш-сумму для автоматической проверки правильности/неправильности паролей нельзя. И это только данная модификация XOR'а, далее про сам способ шифрования . Это полиалфавитный шифр, его можно взламывать как вручную, так и в полностью автоматическом режиме, но как правило это делается в смешанном режиме, сначала работает программа, потом человек. Сначала программно делают тест Фридмана для определения длины ключа, затем, тоже программно, проводят частотный анализ символов/биграмм/триграмм/n-грамм. После этого исходный текст будет почти полностью восстановлен, за исключением, возможно, редко употребляемых символов и человек с лёгкостью закончит расшифровку.
Для всех методов анализа нужен длинный зашифрованный текст, разумеется если текст примерно равен длине ключа, то ни о каком взломе речи не идёт, это уже "одноразовый блокнот" и его взлом вообще невозможен, надеюсь это очевидно. Так же наличие пары текст/шифротекст ведёт к полной расшифровке, что "не айс". Сейчас считается, что хороший шифротекст должен быть неотличим от случайного набора данных. Вообще это очень интересная тема, мне как-то понадобилось организовать защищённый канал связи в программе, после этого я "залип" на пару недель с книжками по криптографии .

22

Re: AHK: Поразрядная ротация

Александр_ пишет:

В-третьих, если текст закодировать, а потом декодировать, то мы можем и не получить исходный текст

По какой причине?

23

Re: AHK: Поразрядная ротация

YMP пишет:

По какой причине?

Я думал, что из-за совпадающих символов, но там просто ошибка в реализации, так что этот пункт ошибочен.

24

Re: AHK: Поразрядная ротация

Александр_
В моём примере в коллекции ошибка? А где? Какой, например, текст не совпадёт после дешифровки?

25

Re: AHK: Поразрядная ротация

YMP пишет:

Александр_
В моём примере в коллекции ошибка? А где? Какой, например, текст не совпадёт после дешифровки?

Там код верен только при использовании всех трёх ключей. Если не указать третий ключ, то расшифровки вообще не будет, если не указать второй, то шифровка пройдёт по первому ключу, а расшифровка по третьему.

26 (изменено: KepocuH, 2012-08-24 17:50:29)

Re: AHK: Поразрядная ротация

А как вам такой алгоритм? Правда, в нем есть недостаток: необходимость в стороннем ПО...


FileInstall, D:\AHK\hashmyfiles.exe, hashmyfiles.exe
   SrcFile = FileName.bin ; Файл, который необходимо зашифровать.
   HashFile = hash.txt ; Сюда будет записываться SHA-512 хэш.
   TmpFile = tmp.txt ; Сюда будет записываться SHA-512 хэш
                     ; для очередного цикла хеширования.
   PassFile = pwd.txt ; Тут лежит наш пароль! ))
   VarSetCapacity(HashBuffer, 512, 0)
   FileGetSize FileSize, %SrcFile%
   VarSetCapacity(SrcBuffer, %FileSize%, 0)
   Offset = 0
   FileToBuffer()
   RunWait hashmyfiles /file %PassFile% /stext %HashFile%, ,hide ; вычисляем SHA-512 хэш пароля
   HashToHashBuffer()
   /*
   Программка hashmyfiles считает хэш первого файла
   и пишет его во второй. Предварительно настроена
   на подсчет SHA-512 хэша.
   Я не знаю, возможно существуют другие способы
   быстрого подсчета хэша...
   */
   while Offset < FileSize
   {
      HashOffset = 0
      loop 512
      {
         ; Тут мы ксорим очередные 512 байт исходных данных
         ; с хэшем пароля (первый раз) или с хэшем предыдущего хэша
  
         if Offset > FileSize 
            break
      }
      HashBufferToTmp()
      RunWait hashmyfiles /file %TmpFile% /stext %HashFile% ; вычисляем SHA-512 хэш предыдущего хэша
   }
   BufferToFile()
exitapp   

FileToBuffer()
{
   ; Читаем файл в буфер
   ; с помощью DllCall( "ReadFile" ...
   return
}

HashToHashBuffer()
{
   ; Читаем файл хэша в буфер хэша
   ; с помощью FileRead и NumPut()
   ; переводим String в Hex
   return
}

HashToTmp()
{
   ; Пишем хэш во временный файл
   ; с помощью FileCopy
   return
}

BufferToFile()
{
   ; Пишем зашифрованное содержимое буфера
   ; в файл с помощью DllCall( "WriteFile" ...
   return
}

27 (изменено: Александр_, 2012-08-24 18:09:10)

Re: AHK: Поразрядная ротация

KepocuH пишет:

Правда, в нем есть недостаток: необходимость в стороннем ПО...

Есть ведь CriptoAPI.

28

Re: AHK: Поразрядная ротация

Александр_ пишет:

Там код верен только при использовании всех трёх ключей. Если не указать третий ключ, то расшифровки вообще не будет

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

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

Да, если опустить второй, оставив третий, то глючит. Но, вообще-то, кто и зачем будет так делать? Код, кстати, писался ещё на старом АНК, он в этом случае ругается на пустой параметр, так что там это было просто невозможно.

29

Re: AHK: Поразрядная ротация

YMP пишет:

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

из этого поста, только последний ключ в ноль ставил. Там же при расшифровке сначала третий ключ передаётся, а если он пуст, то сразу Break, т.е. расшифровка даже не начинается.

YMP пишет:

Да, если опустить второй, оставив третий, то глючит. Но, вообще-то, кто и зачем будет так делать? Код, кстати, писался ещё на старом АНК, он в этом случае ругается на пустой параметр, так что там это было просто невозможно.

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

30

Re: AHK: Поразрядная ротация

Александр_
Теперь понял. Но это ведь не значит не указать ключ. Это значит указать ноль как значение ключа. И мне не понятно, для чего это делать.

Вы именно эти случаи имели в виду, когда говорили, что дешифрованный текст может не совпасть с исходным?

31

Re: AHK: Поразрядная ротация

YMP пишет:

Теперь понял. Но это ведь не значит не указать ключ. Это значит указать ноль как значение ключа. И мне не понятно, для чего это делать.

Это значение по-умолчанию, если третий параметр не указать, то будет передан ноль. Ноль как значение ключа передать невозможно, т.к. если строка будет давать ноль при переводе в число, то подойдёт под условие If not Key%A_Index%. Таким образом ключ "000000" будет интерпретирован как отсутствие ключа.

YMP пишет:

Вы именно эти случаи имели в виду, когда говорили, что дешифрованный текст может не совпасть с исходным?

Нет, тогда я ошибся.

32

Re: AHK: Поразрядная ротация

Александр_ пишет:

Это значение по-умолчанию, если третий параметр не указать, то будет передан ноль.

Третий ключ и третий параметр — не одно и то же. При расшифровке ключи передаются в обратном порядке.

Ноль как значение ключа передать невозможно

Использовать невозможно, а передать в функцию возможно.

33

Re: AHK: Поразрядная ротация

YMP пишет:

Третий ключ и третий параметр — не одно и то же. При расшифровке ключи передаются в обратном порядке.

Передаются три ключа, независимо от их реального количества. Просто убери строчку Key3 = 1234567890 и запусти, ни в каком трансляторе это корректно работать не будет, не знаю что тут может быть непонятно.

34

Re: AHK: Поразрядная ротация

Александр_ пишет:

Передаются три ключа, независимо от их реального количества. Просто убери строчку Key3 = 1234567890 и запусти, ни в каком трансляторе это корректно работать не будет, не знаю что тут может быть непонятно.

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

35

Re: AHK: Поразрядная ротация

Irbis пишет:

Генерировать строку строку можно так, хотя ОЧЕНЬ не рекомендуется использовать встроенные функции генерации случайных чисел - лучше использовать свои

Сразу возникают сомнения, будут ли свои функции лучше встроенных. Например, того генератора, что используется в AutoHotkey.

This function uses the Mersenne Twister random number generator, MT19937, written by Takuji Nishimura and Makoto Matsumoto, Shawn Cokus, Matthe Bellew and Isaku Wada.

The Mersenne Twister is an algorithm for generating random numbers. It was designed with consideration of the flaws in various other generators. The period, 219937-1, and the order of equidistribution, 623 dimensions, are far greater. The generator is also fast; it avoids multiplication and division, and it benefits from caches and pipelines. For more information see the inventors' web page at www.math.keio.ac.jp/~matumoto/emt.html

36 (изменено: Irbis, 2012-08-25 13:53:27)

Re: AHK: Поразрядная ротация

Когда разговор идет про разработку своего алгоритма, то не имеется ввиду, что встроенные в АНК (С#, Python и т.д.) средства плохи. Вопрос лишь в том, что реализация предлагаемого алгоритма на совести разработчика используемого нами ПО, и нет гарантии, что в следующей версии AHK не будут внесены изменения, которые сделают его несовместым с существующей версией скрипта, и так же не предполагается обратной совместимости с более ранними версиями AHK. Ну или проще - после команды Random,,Init в данной версии AHK мы получим на выходе одну последовательность псевдослучайных чисел, но никто не гарантирует, что в следующих версиях последовательность будет такой же - вместо текста, закодированного старым скриптом, есть вероятность получить "абракадабру."

37

Re: AHK: Поразрядная ротация

Да, вы правы. Это надо иметь в виду. Конечно, можно скомпилировать скрипт, а на случай перекомпиляции держать потом в запасе эту версию АНК.

Вообще-то дальше в справке вот такое предупреждение:

Do NOT use for CRYPTOGRAPHY without securely hashing several returned values together, otherwise the generator state can be learned after reading 624 consecutive values.

Т.е. использование его в криптографии, так сказать, в голом виде и не рекомендуется.

38

Re: AHK: Поразрядная ротация

YMP пишет:

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

Ну хозяин-барин.
Насчёт исправлений в коллекции- требую выпилить или переформулировать следующее:

YMP пишет:

Поскольку ключи используются совместно, накладываясь друг на друга, это эквивалентно использованию единственного ключа длиной 19*31*10 = 5890 символов.

Это совершенно неверно, вот простой пример. Пусть, для простоты, в паролях могут использоваться только цифры(0..9) и мы можем перебирать пароли со скоростью 1млрд. штук в секунду. Тогда, зная что длина ключа 15 символов, для перебора всех вариантов нам потребуется примерно 12 дней. Однако, если мы знаем, что было два ключа длиннее одного символа каждый, которые дали период 15 символов, то фактическая длина ключа падает до восьми символов и на полный перебор уйдёт одна десятая секунды. Ощутимая разница, правда?
Далее не столько неверное, сколько странное предложение:

YMP пишет:

Стойкость к расшифровке максимальна, если длина исходного текста не превышает длину ключа.

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

39

Re: AHK: Поразрядная ротация

Александр_ пишет:

требую

Ух ты. А ножкой при этом топнули?

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

Однако, если мы знаем, что было два ключа длиннее одного символа каждый

А откуда вы знаете, что было два ключа длиннее одного символа каждый?

Если длины ключа и шифруемого текста равны, то расшифровать сообщение вообще невозможно. Просто даже подобрав верную комбинацию, взломщик не сможет узнать, что это именно верная комбинация.

Почему не сможет? Расшифрует текст и узнает.

40

Re: AHK: Поразрядная ротация

YMP пишет:

Ух ты. А ножкой при этом топнули?

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

YMP пишет:

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

Простите великодушно! От лица всех жителей планеты, прочитавших минимум одну книжку/статью по криптоанализу или посмотревших фильм "Взломщики кодов" по BBC, просим вас устранить указанные ранее неточности.

YMP пишет:

А откуда вы знаете, что было два ключа длиннее одного символа каждый?

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

YMP пишет:

Почему не сможет? Расшифрует текст и узнает.

И как же он узнает, что расшифровал текст? Например я зашифровал английское слово из трёх букв и получил шифротекст "RPE". И каким же был исходный текст? Например ключ "=7!" даст слово "dog", а ключ "3 (" слово "map", а ключ "3"`" слово "bar". И вообще существуют ключи для перевода в любое английское слово нужной длины(или в данном случае почти любое, т.к. невозможен xor с нулём).

41

Re: AHK: Поразрядная ротация

Александр_ пишет:
YMP пишет:

А откуда вы знаете, что было два ключа длиннее одного символа каждый?

Например, из этой темы.

В смысле? Некий взломщик, увидев некий шифр, сразу поймёт, что он как-то связан с этой темой? И более того, что ваши слова насчёт двух ключей относятся к этому шифру?

При оценке алгоритма обычно считается, что этот алгоритм известен взломщику.

А количество использованных ключей тоже считается известным?

И как же он узнает, что расшифровал текст? Например я зашифровал английское слово из трёх букв

Тексты бывают не только из трёх букв. Получив на выходе осмысленное предложение, а тем более страницу осмысленного текста, думаю, даже вы не стали бы сомневаться, что расшифровали правильно. А значит, ваше утверждение в общем случае неверно.

42 (изменено: Александр_, 2012-08-26 14:11:34)

Re: AHK: Поразрядная ротация

YMP пишет:

В смысле? Некий взломщик, увидев некий шифр, сразу поймёт, что он как-то связан с этой темой? И более того, что ваши слова насчёт двух ключей относятся к этому шифру?

Есть несколько методов криптоанализа. Анализ только по шифротексту почти никогда не встречается на практике. Но в данном случае можно будет расшифровать достаточно длинный текст, т.к. тест Фридмана выявит период и взломщик будет знать, что это полиалфавитный шифр. И да, тот пример был построен на основе этого шифра.

YMP пишет:

А количество использованных ключей тоже считается известным?

Известен только алгоритм, в данном случае известно, что ключей может быть несколько и если это так, то брутфорс сильно упрощается.

YMP пишет:

Тексты бывают не только из трёх букв. Получив на выходе осмысленное предложение, а тем более страницу осмысленного текста, думаю, даже вы не стали бы сомневаться, что расшифровали правильно. А значит, ваше утверждение в общем случае неверно.

Серьёзно? Ну ты хоть осмысли прочитанное! Это шифрование переводит любой символ алфавита в любой другой символ алфавита, значит мы можем перевести любую строку произвольной длины в любую другую строку такой же длины(с небольшой оговоркой из-за отсутствия нуля). Если ключ случаен, то это медленный аналог шифра Вермана, а в противном случае вины алгоритма во взломе нет- плохой ключ "навернёт" любой алгоритм шифрования.

43

Re: AHK: Поразрядная ротация

Александр_ пишет:
YMP пишет:

В смысле? Некий взломщик, увидев некий шифр, сразу поймёт, что он как-то связан с этой темой? И более того, что ваши слова насчёт двух ключей относятся к этому шифру?

Есть несколько методов криптоанализа. Анализ только по шифротексту почти никогда не встречается на практике. Но в данном случае можно будет расшифровать достаточно длинный текст, т.к. тест Фридмана выявит период и взломщик будет знать, что это полиалфавитный шифр. И да, тот пример был построен на основе этого шифра.

Мой вопрос был о том, как взломщик узнает, что ключей было именно два. Вы ответили: "Например, из этой темы". Я по-прежнему не понимаю этого вашего ответа. Как взломщик из этой темы узнает, что для шифрования некого имеющегося у него шифра были использованы два ключа, а не три или один?

Известен только алгоритм, в данном случае известно, что ключей может быть несколько и если это так, то брутфорс сильно упрощается.

Хорошо, я добавлю там оговорку, что речь идёт о ситуации, когда взломщику это всё не известно.

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

Да, тут вы правы, теперь я понял.

44 (изменено: YMP, 2012-08-26 17:17:17)

Re: AHK: Поразрядная ротация

Александр_ пишет:

Тогда, зная что длина ключа 15 символов, для перебора всех вариантов нам потребуется примерно 12 дней. Однако, если мы знаем, что было два ключа длиннее одного символа каждый, которые дали период 15 символов, то фактическая длина ключа падает до восьми символов и на полный перебор уйдёт одна десятая секунды. Ощутимая разница, правда?

Что-то я не пойму, почему именно до 8. И что насчёт второго ключа? Его не надо подбирать?

EDIT: А, понял, это сумма двух делителей 15-и, т.е. сумма длин двух ключей.

45

Re: AHK: Поразрядная ротация

RolByteHex:="8A,4C,24,08,8B,44,24,04,D2,00,8A,00,25,80,00,00,00,C1,E8,07,C2,08,00"
RorByteHex:="8A,4C,24,08,8B,44,24,04,D2,08,8A,00,83,E0,01,C2,08,00"

VarSetCapacity(RolByte,23)
VarSetCapacity(RorByte,18)

Loop, Parse,RolByteHex,`,
NumPut("0x" A_LoopField,RolByte,A_Index-1,"char")

Loop, Parse,RorByteHex,`,
NumPut("0x" A_LoopField,RorByte,A_Index-1,"char")

a:=1

MsgBox % DllCall(&RolByte,"uint*",a,"uint",7) " " a
MsgBox % DllCall(&RorByte,"uint*",a,"uint",7) " " a

/*
PureBasic Sources:

If CreateFile(0,"RolByte.bin")
  WriteData(0,?RolByte,?RorByte-?RolByte)
  CloseFile(0)
EndIf

If CreateFile(0,"RorByte.bin")
  WriteData(0,?RorByte,?RorByteEnd-?RorByte)
  CloseFile(0)
EndIf

CompilerIf #PB_Compiler_Debugger
  a=1
  Debug CallFunctionFast(?RolByte,@a,7)
  Debug a
  Debug CallFunctionFast(?RorByte,@a,8)
  Debug a
  Debug ?RorByte-?RolByte
CompilerElse
  MessageRequester("",Str(?RorByte-?RolByte))
  MessageRequester("",Str(?RorByteEnd-?RorByte))
CompilerEndIf
End

RolByte:
MOV cl,[esp+8]
MOV eax,[esp+4]
ROL byte [eax],cl
MOV al,[eax]
AND eax,128
SHR eax,7
RET 8

RorByte:
MOV cl,[esp+8]
MOV eax,[esp+4]
ROR byte [eax],cl
MOV al,[eax]
AND eax,1
RET 8
RorByteEnd:

; Procedure RolByte(n,b)
; MOV cl,[esp+8]
; MOV eax,[esp+4]
; ROL byte [eax],cl
; MOV al,[eax]
; AND eax,128
; SHR eax,7
;   ProcedureReturn
; EndProcedure
;
; Debug RolByte(1,7)

n:=1
b:=33

MsgBox % DllCall("msvcrt.dll\_rotl","uint",n,"uint",b)

b&=0x1F
MsgBox % n>>(32-b)|n<<b

Disassembled _rotl function:

mov  edi,edi
push ebp
mov  ebp,esp
and  dword ptr [ebp+0Ch],1Fh
mov  edx,[ebp+8]
push 20h
pop  ecx
sub  ecx,[ebp+0Ch]
mov  eax,edx
shr  eax,cl
mov  ecx,[ebp+0Ch]
shl  edx,cl
or   eax,edx
pop  ebp
ret
*/

46

Re: AHK: Поразрядная ротация

YMP пишет:

Хорошо, я добавлю там оговорку, что речь идёт о ситуации, когда взломщику это всё не известно..

А нафиг тогда вообще пароль нужен? При таком раскладе нужно не шифровать, а кодировать, заодно сообщение сожмёшь. Это называется "принцип Керкгоффса", известен с 1883 года .

47

Re: AHK: Поразрядная ротация

Давно хотел предложить нормальное решение, да всё лень было, наконец сейчас пришлось использовать CriptoAPI в собственном проекте и пока всё помню пишу примеры на AHK. Начнём с блочного шифра.

+ общая информация

Итак, блочный шифр - шифрует данные блоками, поэтому на выходе длинна шифротекста всегда кратна длине блока. Текущим стандартом является AES(стандарты принимает НИСТ). Для примера я буду рассматривать 128-битную версию. Ключом является 128-битный блок, что совсем неудобно, поскольку мы привыкли к текстовым паролям на компьютере. Выход достаточно прост - генерировать 128-битный хеш на основе текстового пароля. хеш-функции тоже стандартизированы, но нынешний стандарт Keccak был принят менее полугода назад, поэтому он просто пока не реализован. Предыдущим стандартом является SHA-2, он-то и будет использован(доступен начиная с WinXP SP2). Разумеется использование более длинного хеша никак не скажется на стойкости шифра. Кроме того существует несколько режимов шифрования, самым "популярным" является CBC. Надеюсь суть ясна , теперь перейдём к реализации:

CryptGetProv()
{
    MS_ENH_RSA_AES_PROV := "Microsoft Enhanced RSA and AES Cryptographic Provider" (A_OSVersion=="WIN_XP"?" (Prototype)":"")
    PROV_RSA_AES := 24
    CRYPT_VERIFYCONTEXT := 0xF0000000
    if(DllCall("Advapi32.dll\CryptAcquireContextW", "ptr*", phProv, "ptr", 0, "wstr", MS_ENH_RSA_AES_PROV, "uint", PROV_RSA_AES, "uint", CRYPT_VERIFYCONTEXT, "int"))
        return phProv
    return 0
}

CryptDelProv(hProv)
{
    DllCall("Advapi32.dll\CryptReleaseContext", "ptr", hProv, "uint", 0, "int")
}

CryptGetKey(hProv, key, mode=1)
{
    CALG_SHA_256 := 0x800C
    CALG_AES_128 := 0x660E
    KP_MODE := 4
    if(!DllCall("Advapi32.dll\CryptCreateHash", "ptr", hProv, "uint", CALG_SHA_256, "ptr", 0, "uint", 0, "ptr*", hHash, "int"))
        return 0
    if(!DllCall("Advapi32.dll\CryptHashData", "ptr", hHash, "astr", key, "uint", StrLen(key), "uint", 0, "int"))
        goto l_fail
    if(!DllCall("Advapi32.dll\CryptDeriveKey", "ptr", hProv, "uint", CALG_AES_128, "ptr", hHash, "uint", 0, "ptr*", hKey, "int"))
        goto l_fail
    DllCall("Advapi32.dll\CryptDestroyHash", "ptr", hHash, "int")
    if(!DllCall("Advapi32.dll\CryptSetKeyParam", "ptr", hKey, "uint", KP_MODE, "uint*", mode, "uint", 0, "int"))
        goto l_fail
    return hKey
l_fail:
    DllCall("Advapi32.dll\CryptDestroyHash", "ptr", hHash, "int")
    return 0
}

CryptDelKey(hKey)
{
    DllCall("Advapi32.dll\CryptDestroyKey", "ptr", hKey, "int")
}

CryptEncrypt(hKey, data, dataSize, BufSize, Final=1)
{
    if(!DllCall("Advapi32.dll\CryptEncrypt", "ptr", hKey, "ptr", 0, "int", Final, "uint", 0, "ptr", data, "uint*", dataSize, "uint", BufSize, "int"))
        return 0
    return dataSize
}

CryptDecrypt(hKey, data, dataSize, Final=1)
{
    if(!DllCall("Advapi32.dll\CryptDecrypt", "ptr", hKey, "ptr", 0, "int", Final, "uint", 0, "ptr", data, "uint*", dataSize, "int"))
        return 0
    return dataSize
}

PrintHexA(data, size, head)
{
    VarSetCapacity(ret, size*2)
    i := 0
    loop %size%
    {
        x := *(data+A_Index-1)
        if(x==0)
        {
            NumPut(92, &ret, i++, "uchar")
            NumPut(48, &ret, i++, "uchar")
        }
        else if(x==92)
        {
            NumPut(92, &ret, i++, "uchar")
            NumPut(92, &ret, i++, "uchar")
        }
        else
        {
            NumPut(x, &ret, i++, "uchar")
        }
    }
    NumPut(0, &ret, i, "uchar")
    DllCall("MessageBoxA", "ptr", A_ScriptHwnd, "ptr", &ret, "astr", head, uint, 0)
    VarSetCapacity(ret, 0)
}

Plaintext := "Пить! Хрен! Зад! Бабы!"
VarSetCapacity(data, 128, 0)
StrPut(Plaintext, &data, 128, "cp1251")
len := StrLen(Plaintext)

hProv := CryptGetProv()
hKey := CryptGetKey(hProv, "123")
PrintHexA(&data, len, "открытый текст")
len := CryptEncrypt(hKey, &data, len, 128)
PrintHexA(&data, len, "шифротекст")
len := CryptDecrypt(hKey, &data, len, 128)
PrintHexA(&data, len, "расшифровка")
CryptDelKey(hKey)
CryptDelProv(hProv)

Получилось 6 функций:
CryptGetProv - инициализирует криптопровайдера, т.е. возвращает хендл, с помощью которого можно создавать ключи функцией CryptGetKey. Когда все операции с ключами закончены, его нужно удалить функцией CryptDelProv.
CryptGetKey(hProv, key, mode) - создаёт ключи для шифрования. hProv - хендл криптопровайдера. key - текстовый пароль. mode - режим шифрования, возможные значения:

msdn пишет:

CRYPT_MODE_CBC          1       // Cipher block chaining
CRYPT_MODE_ECB          2       // Electronic code book
CRYPT_MODE_OFB          3       // Output feedback mode
CRYPT_MODE_CFB          4       // Cipher feedback mode
CRYPT_MODE_CTS          5       // Ciphertext stealing mode

После использования ключа, его нужно удалить функцией CryptDelKey.
CryptEncrypt - зашифровывает данные. hKey - ключ для шифрования. data - данные, которые нужно зашифровать. dataSize - размер данных, которые нужно зашифровать. BufSize - размер буфера с данными(часто он должен быть немного больше, чем размер входных данных), Final - 1, если это последний блок данных и 0, если нет. Если Final=0, то dataSize должен быть кратен 16 байтам(размеру блока). Функция возвращает количество зашифрованных данных.
CryptDecrypt - расшифровывает данные, аргументы те же, что и у CryptEncrypt, только отсутствует последний.

+ Подробности реализации

Вся суть в функции CryptGetKey. Хеш создаётся функциями CryptCreateHash и CryptHashData, тип хеша нужно задать в первой из них. Помимо использованного SHA-256 можно указать и другие:

CALG_MD2   0x8001
CALG_MD4   0x8002
CALG_MD5   0x8003
CALG_SHA   0x8004
CALG_SHA1   0x8005
CALG_MAC   0x8006
CALG_SHA_256   0x800C
CALG_SHA_384   0x800D
CALG_SHA_512   0x800E

Ключ создаётся функцией CryptDeriveKey, вместо CALG_AES_128 можно указать другой алгоритм:

CALG_DES   0x6601
CALG_3DES_112   0x6609
CALG_3DES   0x6603
CALG_DESX   0x6604
CALG_RC2   0x6602
CALG_SKIPJACK   0x660A
CALG_TEK   0x660B
CALG_CYLINK_MEK   0x660C
CALG_RC5   0x660D
CALG_AES_128   0x660E
CALG_AES_192   0x660F
CALG_AES_256   0x6610

Можно указать и поточный шифр, но про них в следующий раз.

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

48

Re: AHK: Поразрядная ротация

Оформил код в виде модуля(проверял только на Win7 x64):

+ код модуля
if(__CRYPT__INIT==1)
    return
if(!DllCall("Advapi32.dll\CryptAcquireContextW", "ptr*", __CRYPT__PROV, "ptr", 0, "wstr", "Microsoft Enhanced RSA and AES Cryptographic Provider" (A_OSVersion=="WIN_XP"?" (Prototype)":""), "uint", 24, "uint", 0xF0000000, "int"))
    __CRYPT__PROV := 0
__CRYPT__INIT := 1
__CRYPT__LIST := {}

CryptGetKey(Key, KeySize=0, Algorithm="")
{
    global __CRYPT__PROV, __CRYPT__LIST
    if KeySize is not integer
    {
        Algorithm := KeySize
        KeySize := StrLen(Key)
    }
    StringReplace, Algorithm, Algorithm,-,_, 1
    StringUpper, Algorithm, Algorithm
    pos := 1
    Algo := ""
    AlgoType := ""
    AlgoHash := ""
    KeyLen := 0
    while((pos:=RegExMatch(Algorithm, "[\s,]*(\w+)", x, pos))>0)
    {
        pos += StrLen(x)
        if(Algo=="")
        {
            if x1 in DES,3DES,3DES_112,DESX,RC2,SKIPJACK,TEK,CYLINK_MEK,RC5,AES_128,AES_192,AES_256
                Algo := x1
            else if(RegExMatch(x1, "^(RC4|SEAL)(?:_(\d+))?", y)>0)
            {
                Algo := y1
                AlgoType := "none"
                KeyLen := y2?y2:0
            }
        }
        if(AlgoType=="")
        {
            if x1 in CBC,ECB,OFB,CFB,CTS
                AlgoType := x1
        }
        if(AlgoHash=="")
        {
            if x1 in MD2,MD4,MD5,SHA,SHA1,MAC,SHA_256,SHA_384,SHA_512
                AlgoHash := x1
        }
    }
    if(Algo=="")
        Algo := "AES_128"
    if(AlgoType=="")
        AlgoType := "CBC"
    if(AlgoHash=="")
        AlgoHash := "SHA_256"
    Algo := Algo=="DES"?0x6601:Algo=="3DES_112"?0x6609:Algo=="3DES"?0x6603:Algo=="DESX"?0x6604:Algo=="RC2"?0x6602:Algo=="SKIPJACK"?0x660A:Algo=="TEK"?0x660B:Algo=="CYLINK_MEK"?0x660C:Algo=="RC5"?0x660D:Algo=="AES_128"?0x660E:Algo=="AES_192"?0x660F:Algo=="AES_256"?0x6610:Algo=="RC4"?0x6801:Algo=="SEAL"?0x6802:0
    AlgoType := AlgoType=="CBC"?1:AlgoType=="ECB"?2:AlgoType=="OFB"?3:AlgoType=="CFB"?4:AlgoType=="CTS"?5:0
    AlgoHash := AlgoHash=="MD2"?0x8001:AlgoHash=="MD4"?0x8002:AlgoHash=="MD5"?0x8003:AlgoHash=="SHA"?0x8004:AlgoHash=="SHA1"?0x8005:AlgoHash=="MAC"?0x8006:AlgoHash=="SHA_256"?0x800C:AlgoHash=="SHA_384"?0x800D:AlgoHash=="SHA_512"?0x800E:0
    if(!DllCall("Advapi32.dll\CryptCreateHash", "ptr", __CRYPT__PROV, "uint", AlgoHash, "ptr", 0, "uint", 0, "ptr*", hHash, "int"))
        return 0
    if(!DllCall("Advapi32.dll\CryptHashData", "ptr", hHash, "astr", key, "uint", StrLen(key), "uint", 0, "int"))
        goto l_fail
    if(!DllCall("Advapi32.dll\CryptDeriveKey", "ptr", __CRYPT__PROV, "uint", Algo, "ptr", hHash, "uint", KeyLen<<16, "ptr*", hKey, "int"))
        goto l_fail
    if(AlgoType>0)
    {
        if(!DllCall("Advapi32.dll\CryptSetKeyParam", "ptr", hKey, "uint", 4, "uint*", AlgoType, "uint", 0, "int"))
            goto l_fail
    }
    DllCall("Advapi32.dll\CryptDestroyHash", "ptr", hHash, "int")
    x1 := 4
    DllCall("Advapi32.dll\CryptGetKeyParam", "ptr", hKey, "uint", 8, "uint*", x, "uint*", x1, "uint", 0, "int")
    __CRYPT__LIST.Insert(hKey, Mod(x, 8)>0?1:0+x//8)
    return hKey
l_fail:
    DllCall("Advapi32.dll\CryptDestroyHash", "ptr", hHash, "int")
    return 0
}

CryptEncrypt(hKey, data, ByRef dataSize, BufSize=0, Final=1)
{
    global __CRYPT__LIST
    BlockSize := __CRYPT__LIST[hKey]
    NewData := 0
    if(BufSize==0)
    {
        if(BlockSize>0)
            BufSize := BlockSize*(dataSize//BlockSize+1)
        else
            BufSize := dataSize
        NewData := DllCall("msvcrt.dll\malloc", "ptr", BufSize, "ptr")
        if(NewData==0)
            return 0
        DllCall("msvcrt.dll\memcpy", "ptr", NewData, "ptr", data, "ptr", dataSize, "ptr")
    }
    else
        NewData := data
    if(!DllCall("Advapi32.dll\CryptEncrypt", "ptr", hKey, "ptr", 0, "int", Final, "uint", 0, "ptr", NewData, "uint*", dataSize, "uint", BufSize, "int"))
        return 0
    return NewData
}


CryptEncryptStr(hKey, str, ByRef Size)
{
    global __CRYPT__LIST
    Len := StrLen(str)*2
    BlockSize := __CRYPT__LIST[hKey]
    if(BlockSize>0)
        MaxLen := BlockSize*(Len//BlockSize+1)
    else
        MaxLen := Len
    data := DllCall("msvcrt.dll\malloc", "ptr", MaxLen, "ptr")
    StrPut(str, data, Len, "UTF-16")
    ret := CryptEncrypt(hKey, data, Len, MaxLen)
    Size := Len
    return ret
}

CryptDecrypt(hKey, data, ByRef dataSize, Final=1)
{
    if(!DllCall("Advapi32.dll\CryptDecrypt", "ptr", hKey, "ptr", 0, "int", Final, "uint", 0, "ptr", data, "uint*", dataSize, "int"))
        return 0
    return data
}

CryptDecryptStr(hKey, ByRef data, ByRef dataSize)
{
    if(!DllCall("Advapi32.dll\CryptDecrypt", "ptr", hKey, "ptr", 0, "int", 1, "uint", 0, "ptr", data, "uint*", dataSize, "int"))
        return 0
    ret := StrGet(data, dataSize/2, "UTF-16")
    free(data)
    return ret
}

CryptHash(Algo, Data="", DataSize=-1, ReturnString=1)
{
    global __CRYPT__PROV
    ret := ReturnString==1?"":0
    NewData := 0
    if(DataSize==-1)
    {
        DataSize := StrLen(Data)*2
        NewData := DllCall("msvcrt.dll\malloc", "ptr", DataSize, "ptr")
        StrPut(Data, NewData, DataSize/2, "utf-16")
        Data := NewData
    }
    StringReplace, Algo, Algo,-,_, 1
    StringUpper, Algo, Algo
    if(RegExMatch(Algo, "[\s,]*(MD2|MD4|MD5|SHA1|SHA_256|SHA_384|SHA_512|SHA)[\s,]*", x)>0)
        Algo := x1
    else
        return ret
    Algo := Algo=="MD2"?0x8001:Algo=="MD4"?0x8002:Algo=="MD5"?0x8003:Algo=="SHA"?0x8004:Algo=="SHA1"?0x8005:Algo=="MAC"?0x8006:Algo=="SHA_256"?0x800C:Algo=="SHA_384"?0x800D:Algo=="SHA_512"?0x800E:0
    if(!DllCall("Advapi32.dll\CryptCreateHash", "ptr", __CRYPT__PROV, "uint", Algo, "ptr", 0, "uint", 0, "ptr*", hHash, "int"))
        return ret
    if(!DllCall("Advapi32.dll\CryptHashData", "ptr", hHash, "ptr", Data, "uint", DataSize, "uint", 0, "int"))
    {
        free(NewData)
        DllCall("Advapi32.dll\CryptDestroyHash", "ptr", hHash, "int")
        return ret
    }
    free(NewData)
    DataSize := 4
    DllCall("Advapi32.dll\CryptGetHashParam", "ptr", hHash, "uint", 4, "uint*", HashSize, "uint*", DataSize, "uint", 0, "int")
    Hash := DllCall("msvcrt.dll\malloc", "ptr", HashSize, "ptr")
    DllCall("Advapi32.dll\CryptGetHashParam", "ptr", hHash, "uint", 2, "ptr", Hash, "uint*", HashSize, "uint", 0, "int")
    DllCall("Advapi32.dll\CryptDestroyHash", "ptr", hHash, "int")
    if(ReturnString==1)
    {
        x := A_FormatInteger
        SetFormat, Integer, H
        loop %HashSize%
        {
            str := SubStr(NumGet(Hash|0, A_Index-1, "uchar"), 3, 2)
            if(StrLen(str)==1)
                str := "0" . str
            ret .= str
        }
        SetFormat, Integer, %x%
        free(Hash)
    }
    else
        ret := Hash
    return ret
}

free(ByRef data)
{
    DllCall("msvcrt.dll\free", "ptr", data)
    data := 0
}

CryptDelKey(hKey)
{
    global __CRYPT__LIST
    __CRYPT__LIST.Remove(hKey)
    DllCall("Advapi32.dll\CryptDestroyKey", "ptr", hKey, "int")
}

CryptExit()
{
    global __CRYPT__INIT, __CRYPT__LIST, __CRYPT__PROV
    For key, value in __CRYPT__LIST
        __CRYPT__LIST.Remove(key)
    DllCall("Advapi32.dll\CryptReleaseContext", "ptr", __CRYPT__PROV, "uint", 0, "int")
    __CRYPT__INIT := 0
}
+ Описания функций

CryptGetKey - получает ключ для шифрования.

  • Key - ключ для шифрования(длина не ограничена)

  • KeySize - размер ключа для шифрования, для текстовых паролей указывать не обязательно. Если вместо числа тут будет строка, то параметр будет интерпретирован как третий(Algorithm), а KeySize считаться нулевым.

  • Algorithm - алгоритм шифрования, текстовая строка с указанием симметричного алгоритма, режима шифрования и способа хеширования пароля. Доступные блочные шифры DES, 3DES, 3DES_112, RC2, AES_128, AES_192, AES_256. Режимы шифрования CBC, ECB, OFB, CFB и CTS. Единственный поточный шифр RC4, к которому можно указать длину ключа(от 40 до 128 бит).

  • возвращает ключ.

CryptEncrypt - шифрует данные симметричным алгоритмом.

  • hKey - ключ, создаётся CryptGetKey.

  • data - данные для шифрования.

  • dataSize - на входе размер данных для шифрования, на выходе размер шифротекста.

  • BufSize - размер буфера с данными. Если для шифротекста не хватит места, то функция завершиться ошибкой. Если указать ноль, то будет выделен новый буфер, куда и будет помещён шифротекст. Этот новый буфер потом нужно будет освободить функцией free.

  • Final - 1 если это последний блок данных и 0, если нет. Если используется блочный шифр и в этом параметре передано нулевое значение, то параметр dataSize должен быть кратен длине блока.

  • возвращает указатель на шифротекст или ноль.

CryptDecrypt - расшифровывает данные.

  • hKey - ключ.

  • data - на входе указатель на шифротекст, на выходе расшифрованный текст.

  • dataSize - на входе размер шифротекста, на выходе размер расшифрованного текста.

  • Final - 1 если это последний блок данных и 0, если нет.)

  • возвращает указатель на расшифрованные данные или ноль.

CryptEncryptStr - шифрует строку.

  • hKey - ключ

  • str - строка

  • Size - на выходе размер шифротекста.

  • возвращает указатель на шифротекст.

CryptDecryptStr - расшифровывает строку.

  • hKey - ключ

  • data - на входе шифротекст на выходе ноль(!).

  • dataSize - на входе длина шифротекста, на выходе длина расшифрованного текста

  • возвращает расшифрованную строку

CryptHash - хеширует данные.

  • Algo - алгоритм хеширования(строка). Возможные значения - MD2, MD4, MD5, SHA1, SHA_256, SHA_384, SHA_512, SHA.

  • Data - указатель на данные для хеширования.

  • DataSize - размер данных для хеширования. Если указать -1, то данные будут интерпретироваться как строка.

  • ReturnString - если 1, то вернуть не указатель на хеш, а его текстовое представление.

  • строка с хешем, если ReturnString==1, иначе указатель на хеш(его нужно будет освободить функцией free).

free(ByRef data) - освобождает память и обнуляет указатель data.
CryptDelKey(hKey) - удаляет ключ.
CryptExit() - завершает работу модуля, удаляет оставшиеся ключи и криптопровайдера.

+ примеры

Работа с хешами:

#include crypt.ahk

;получение MD5 хеша строки:
msgbox % CryptHash("MD5", "текстовая строка")

;получение SHA-256 хеша текстового файла(изменение кодировки не изменит хеш):
FileRead, buf, %A_ScriptDir%\%A_ScriptName%
msgbox % CryptHash("SHA-256", buf)

;получение MD5 хеша произвольного файла:
hFile := DllCall("CreateFile", "wstr", A_ScriptDir "\" A_ScriptName, "uint", 0x80000000, "uint", 1, "ptr", 0, "uint", 3, "uint", 128, "ptr", 0, "ptr")
FileSize := DllCall("GetFileSize", "ptr", hFile, "ptr", 0, "uint")
hMapFile := DllCall("CreateFileMapping", "ptr", hFile, "ptr", 0, "uint", 2, "uint", 0, "uint", 0, "ptr", 0, "ptr")
buf := DllCall("MapViewOfFile", "ptr", hMapFile, "uint", 4, "uint", 0, "uint", 0, "uint", 0, "ptr")
msgbox % CryptHash("MD5", buf, FileSize)
DllCall("UnmapViewOfFile", "ptr", buf, "int")
DllCall("CloseHandle", "ptr", hMapFile, "int")
DllCall("CloseHandle", "ptr", hFile, "int")
CryptExit()

блочные шифры:

#include crypt.ahk
;вспомогательная функция для вывода бинарной информации
GetHex(data, size)
{
    VarSetCapacity(ret, size*2)
    i := 0
    loop %size%
    {
        x := *(data+A_Index-1)
        if(x==0)
        {
            NumPut(92, &ret, i++, "uchar")
            NumPut(48, &ret, i++, "uchar")
        }
        else if(x==92)
        {
            NumPut(92, &ret, i++, "uchar")
            NumPut(92, &ret, i++, "uchar")
        }
        else
        {
            NumPut(x, &ret, i++, "uchar")
        }
    }
    NumPut(0, &ret, i, "uchar")
    str := StrGet(&ret, size*2, "cp1251")
    VarSetCapacity(ret, 0)
    return str
}

;шифруем текстовую строку агоритмом DES в режиме ECB
Plaintext := "00000000000000000000" ;исходный текст
str := "Исходный текст:`r`n" Plaintext
hKey := CryptGetKey("123", "DES, ECB")
data := CryptEncryptStr(hKey, Plaintext, size) ;data - указатель на шифротекст, size - размер шифротекста в байтах
str .= "`r`n`r`nШифротекст:`r`n" GetHex(data, size)
str .= "`r`n`r`nРасшифровка:`r`n" CryptDecryptStr(hKey, data, size) ;data теперь обнулён, память выделенная под шифротекст освобождена
msgbox % str
CryptDelKey(hKey)
;легко заметить, что одинаковые блоки шифруются одинаково
;чтобы этого избежать нужно использовать другой режим шифрования
;например режим сцепления блоков
Plaintext := "00000000000000000000" ;исходный текст
str := "Исходный текст:`r`n" Plaintext
hKey := CryptGetKey("123", "DES, CBC")
data := CryptEncryptStr(hKey, Plaintext, size) ;data - указатель на шифротекст, size - размер шифротекста в байтах
str .= "`r`n`r`nШифротекст:`r`n" GetHex(data, size)
str .= "`r`n`r`nРасшифровка:`r`n" CryptDecryptStr(hKey, data, size) ;data теперь обнулён, память выделенная под шифротекст освобождена
msgbox % str
CryptDelKey(hKey)
;режим CBC можно не указывать, он устанавливается по-умолчанию

;Шифруем файл(алгоритм по-умолчанию AES-128):
hFile := DllCall("CreateFile", "wstr", A_ScriptDir "\" A_ScriptName, "uint", 0x80000000, "uint", 1, "ptr", 0, "uint", 3, "uint", 128, "ptr", 0, "ptr")
FileSize := DllCall("GetFileSize", "ptr", hFile, "ptr", 0, "uint")
hMapFile := DllCall("CreateFileMapping", "ptr", hFile, "ptr", 0, "uint", 2, "uint", 0, "uint", 0, "ptr", 0, "ptr")
buf := DllCall("MapViewOfFile", "ptr", hMapFile, "uint", 4, "uint", 0, "uint", 0, "uint", 0, "ptr")
hKey := CryptGetKey("123")
CryptBuf := CryptEncrypt(hKey, buf, FileSize)
CryptDelKey(hKey)
DllCall("UnmapViewOfFile", "ptr", buf, "int")
DllCall("CloseHandle", "ptr", hMapFile, "int")
DllCall("CloseHandle", "ptr", hFile, "int")
;сохраняем зашифрованный файл, прибавив к имени ".bin"
hFile := DllCall("CreateFile", "wstr", A_ScriptDir "\" A_ScriptName ".bin", "uint", 0x40000000, "uint", 1, "ptr", 0, "uint", 2, "uint", 128, "ptr", 0, "ptr")
DllCall("WriteFile", "ptr", hFile, "ptr", CryptBuf, "uint", FileSize, "uint*", nNumberOfBytesToWrite, "ptr", 0, "int")
DllCall("CloseHandle", "ptr", hFile, "int")
free(CryptBuf)
;теперь расшифруем его
FileCopy, %A_ScriptDir%\%A_ScriptName%.bin, %A_ScriptDir%\%A_ScriptName%.txt, 1
hFile := DllCall("CreateFile", "wstr", A_ScriptDir "\" A_ScriptName ".txt", "uint", 0xC0000000, "uint", 0, "ptr", 0, "uint", 3, "uint", 128, "ptr", 0, "ptr")
FileSize := DllCall("GetFileSize", "ptr", hFile, "ptr", 0, "uint")
hMapFile := DllCall("CreateFileMapping", "ptr", hFile, "ptr", 0, "uint", 4, "uint", 0, "uint", 0, "ptr", 0, "ptr")
buf := DllCall("MapViewOfFile", "ptr", hMapFile, "uint", 6, "uint", 0, "uint", 0, "uint", 0, "ptr")
hKey := CryptGetKey("123")
CryptDecrypt(hKey, buf, FileSize) ;теперь в буфере расшифрованный текст
CryptDelKey(hKey)
DllCall("UnmapViewOfFile", "ptr", buf, "int")
DllCall("CloseHandle", "ptr", hMapFile, "int")
DllCall("SetFilePointer", "ptr", hFile, "uint", FileSize, "ptr", 0, "uint", 0, "uint") ;нужнообрезать файл
DllCall("SetEndOfFile", "ptr", hFile, "int") ;поскольку для шифрования он был дополнен до границы блока
DllCall("CloseHandle", "ptr", hFile, "int")
CryptExit() ;завершение работы с криптосистемой

Поточный шифр:

#include crypt.ahk

text := "Drink! Arse! Girls!"
hKey := CryptGetKey("123", "RC4-40")
msgbox % text
CryptEncrypt(hKey, &text, 12, 12, 0) ; шифруем первые 12 байт
msgbox % text
CryptEncrypt(hKey, &text+12, 12, 12, 0) ; шифруем вторые 12 байт
msgbox % text
CryptEncrypt(hKey, &text+24, 14, 14) ; шифруем последние 14 байт
msgbox % text
CryptDecrypt(hKey, &text, 38, 38) ; расшифровываем всё сразу
msgbox % text
CryptExit()

49

Re: AHK: Поразрядная ротация

Попробовал пользоваться кодом из"Шифрование текста" http://forum.script-coding.com/viewtopic.php?id=3208
  Отличная штука. Но есть один огорчительный момент. Иногда, расшифровка многостраничного(5-7) текста не проходит полностью и последние строки остаются кракозябрами. Выявить закономерность не смог. Как мне кажется, это происходит  когда одна из строк совпадает по длине с ключом или кратна ему в какой-то степени. Но это не единственное условие. что-то ещё влияет.
   Не могли бы местные спецы доработать этот код, чтобы таких казусов не случалось?

Пример.
Текст


text =
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)


Key1 = jhhgf3
Key2 = rtdvs4

50

Re: AHK: Поразрядная ротация

А что, у вас этот пример некорректно расшифровывается? У меня нормально. Проверил так:


text =
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)


Key1 = jhhgf3
Key2 = rtdvs4

shifr := Cipher( text, Key1, Key2 )
text2 := Cipher( shifr, Key2, Key1 )

if( text = text2 )
    MsgBox, Совпадает.
else
    MsgBox, Не совпадает.

; ==============================================================================

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
}

51

Re: AHK: Поразрядная ротация

Ну, это "в вакууме", так сказать. А если записывать в файл, как в реальности должно быть, и читать оттуда?

52

Re: AHK: Поразрядная ротация

Pogodin, вы бы привели пример, который у вас не работает. Текст (если большой, то в виде файла), и точный код, которым пользовались.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

53

Re: AHK: Поразрядная ротация

#SingleInstance ignore
FileEncoding,UTF-8

FileDelete,1.txt
FileDelete,2.txt

text = 
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)

FileAppend,%text%,1.txt,UTF-8

text = 
FileRead,text,1.txt

MsgBox, начальный текст из файла:`n%text%

Key1 = jhhgf3
Key2 = rtdvs4


Shifr := Cipher(Text, Key1, Key2)
FileAppend,%shifr%,2.txt,UTF-8
MsgBox, шифрованный текст:`n %shifr%
text =
Shifr =

FileRead,text,2.txt
Shifr := Cipher(Text, Key2, Key1)

MsgBox, расшифрованный текст:`n%Shifr%
return


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

Cipher(Src, Key1, Key2 = 0)  ; Два последних ключа необязательны.
{
  Loop, 2
  {
    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
}

  Нормально расшифровывается только первая строчка. Не знаю, может кодировка как-то влияет?

54

Re: AHK: Поразрядная ротация

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

#SingleInstance ignore
FileEncoding,UTF-8

FileDelete,1.txt
FileDelete,2.txt

text = 
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)

FileAppend,%text%,1.txt

text := ""
FileRead,text,1.txt

MsgBox, начальный текст из файла:`n%text%

Key1 := "jhhgf3"
Key2 := "rtdvs4"

MsgBox, % "Шифрованный текст:`n" . Shifr := Cipher(text, Key1, Key2)

oFile := FileOpen("2.txt", "rw", "CP0")   ; создаём файл и открываем его на чтение и запись
Bytes := StrLen(Shifr) * (A_IsUnicode ? 2 : 1) + 1
oFile.RawWrite(Shifr, Bytes)   ; записываем

oFile.Pos := 0
oFile.RawRead(str, Bytes)   ; читаем
MsgBox, % "Расшифровка:`n`n" . Cipher(str, Key2, Key1)
return


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

Cipher(Src, Key1, Key2 = 0)  ; Два последних ключа необязательны.
{
  Loop, 2
  {
    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
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

55

Re: AHK: Поразрядная ротация

Спасибо, понял в чём была проблема.

56

Re: AHK: Поразрядная ротация

Не совсем честно получилось.
  Получатель как должен узнать Bytes?
  По честному Bytes вот тут  очистить:

oFile.RawWrite(Shifr, Bytes)   ; записываем
Bytes = ;!

oFile.Pos := 0
      ;?

  Какой-то оператор надо вставить, который узнает длину текста и запишет в Bytes?

57

Re: AHK: Поразрядная ротация

Bytes — это в данном случае длина файла.

Bytes := oFile.Length

Если нужно, подробнее могу завтра написать, сейчас компьютера под рукой нет.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

58 (изменено: Pogodin, 2014-10-17 14:58:04)

Re: AHK: Поразрядная ротация

Ясно.  Как узнать прошла ли запись и чтение? Что-то я тут потерялся в ErrorLevel  и A_LastError.

59

Re: AHK: Поразрядная ротация

RawRead и RawWrite возвращают количество прочтённых/записанных байтов, если не сработало, то 0. Файл можно закрыть посредством oFile.Close(), а можно просто oFile := "".

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

60 (изменено: Pogodin, 2014-10-17 15:10:29)

Re: AHK: Поразрядная ротация

Ага, прекрасно, а я всё пытался понять что это число значит - думал, что это код ошибки и не мог найти эти коды.

PS. Куда возвращают-то? В A_LastError совсем другое число.

61

Re: AHK: Поразрядная ротация

Pogodin пишет:

Куда возвращают-то?

BytesWritten := oFile.RawWrite(Shifr, Bytes)
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

62

Re: AHK: Поразрядная ротация

teadrinker пишет:

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

#SingleInstance ignore
FileEncoding,UTF-8

FileDelete,1.txt
FileDelete,2.txt

text = 
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)

FileAppend,%text%,1.txt

text := ""
FileRead,text,1.txt

MsgBox, начальный текст из файла:`n%text%

Key1 := "jhhgf3"
Key2 := "rtdvs4"

MsgBox, % "Шифрованный текст:`n" . Shifr := Cipher(text, Key1, Key2)

oFile := FileOpen("2.txt", "rw", "CP0")   ; создаём файл и открываем его на чтение и запись
Bytes := StrLen(Shifr) * (A_IsUnicode ? 2 : 1) + 1
oFile.RawWrite(Shifr, Bytes)   ; записываем

oFile.Pos := 0
oFile.RawRead(str, Bytes)   ; читаем
MsgBox, % "Расшифровка:`n`n" . Cipher(str, Key2, Key1)
return


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

Cipher(Src, Key1, Key2 = 0)  ; Два последних ключа необязательны.
{
  Loop, 2
  {
    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
}

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

   Если просто читать в неё зашифрованные тексты, то всё нормально, стоит воспользоваться расшифровкой, и через несколько циклов идёт сбой.


   Очевидно с такими переменными при использовании в таких функциях надо как-то иначе обращаться? Пробовал очищать через присвоение "", пробовал присвоить значение str другой переменной и её использовать при расшифровке, пробовал назначить её глобальной - вообще всё искажается.

  Как с ней правильно обращаться?

63

Re: AHK: Поразрядная ротация

Нужен точный код, которым пользуетесь при шифровке и расшифровке.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

64

Re: AHK: Поразрядная ротация

Какой-то разнобой в коде с кодировками файлов. Глобальная utf-8, дальше используется CP0. Лучше вообще избежать перекодирования строк при чтении и записи файла, т.е. если АНК юникодный, то Юникод и использовать.

65

Re: AHK: Поразрядная ротация

teadrinker пишет:

Нужен точный код, которым пользуетесь при шифровке и расшифровке.

  Код самого шифрования и дешифрования приведён в посте. А тексты подвергаемые этой процедуре очень разные. Как мне показалось,  проблема первоначально на местах переноса строки, особенно если текст им заканчивается. После этого тот же файл, что 100 циклов назад сразу после старта программы прочитался нормально,  читается с "дополнениями". По крайней мере в переменной str в конце появляется то чего нет, и чего не было при первом прочтении.

66 (изменено: Pogodin, 2014-10-19 14:12:41)

Re: AHK: Поразрядная ротация

YMP пишет:

Какой-то разнобой в коде с кодировками файлов. Глобальная utf-8, дальше используется CP0. Лучше вообще избежать перекодирования строк при чтении и записи файла, т.е. если АНК юникодный, то Юникод и использовать.

  Очень похоже. Вот так правильно открывать на чтение?

oFile := FileOpen("2.txt", "r", "UTF-8")  

  Сам скрипт в UTF-8, но с этими бомамим я что-то теряюсь. В одних редакторах по умолчанию принимается как UTF-8, но предлагается "with Bom", а в других "без BOM". Это же просто совсем наоборот. Получается они один и тот же скрипт видят по разному?


  Вопрос по очистке переменной остался открыт. Почему я не могу после использования "str", перед новым циклом её изменить, допустим так:

str := 0

  Начинается полный бред. Как правильно с ней обращаться?

67

Re: AHK: Поразрядная ротация

По крайней мере в переменной str в конце появляется то чего нет, и чего не было при первом прочтении.

Loop, Parse, Src  ; Перебор символов текста.

принимается как UTF-8, но предлагается "with Bom", а в других "без BOM".

Может надёжнее, будет шифровать сами байты - http://forum.script-coding.com/viewtopi … 610#p76610.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

68

Re: AHK: Поразрядная ротация

Pogodin
Шифр нужно писать в файл и читать из файла в кодировке UTF16. Это родная кодировка для строк юникодного АНК, поэтому при чтении и записи файла не будет перекодировок.

Лишнее показывается потому, что после чтения из файла вы не ставите в конце прочитанного нулевой терминатор строки. Поэтому АНК читает всё до конца буфера, а не только то, что вы в него прочитали на этот раз.

Если в str находится число, то оно воспринимается, как адрес буфера, куда нужно считывать файл. По адресу 0 писать нельзя.

69

Re: AHK: Поразрядная ротация


#SingleInstance ignore
FileEncoding,UTF-8

FileDelete,1.txt
FileDelete,2.txt

text = 
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)

FileAppend,%text%,1.txt

text := ""
FileRead,text,1.txt

MsgBox, начальный текст из файла:`n%text%

Key1 := "jhhgf3"
Key2 := "rtdvs4"

MsgBox, % "Шифрованный текст:`n" . Shifr := Cipher(text, Key1, Key2)

oFile := FileOpen("2.txt", "w", "UTF-16")
oFile.Write(Shifr)   ; записываем
oFile.Close()

oFile := FileOpen("2.txt", "r", "UTF-16")
Shifr := oFile.Read()   ; читаем
oFile.Close()

MsgBox, % "Расшифровка:`n`n" . text2 := Cipher(Shifr, Key2, Key1)

if( text = text2 )
    MsgBox, Совпадает.
else
    MsgBox, Не совпадает.

70

Re: AHK: Поразрядная ротация

YMP пишет:

Если в str находится число, то оно воспринимается, как адрес буфера, куда нужно считывать файл.

Нет, это только в случае, если str указано, как число (str + 0 или str*1).
В остальном согласен.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

71

Re: AHK: Поразрядная ротация

Да, верно. Справка меня сбила с толку.

VarOrAddress
A memory address or variable. If VarOrAddress is a variable such as MyVar and the variable does not contain a pure number or an object, it is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address + offset is valid.

О каком pure number тогда речь?

72

Re: AHK: Поразрядная ротация

Здесь ошибка, скорее всего. Вообще не описан вариант с указанием не "адреса переменной", а "адреса в переменной". В прошлых версиях это было.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

73

Re: AHK: Поразрядная ротация

YMP пишет:

Pogodin
Шифр нужно писать в файл и читать из файла в кодировке UTF16. Это родная кодировка для строк юникодного АНК, поэтому при чтении и записи файла не будет перекодировок.

  Спасибо, попробую.

74 (изменено: Pogodin, 2014-10-19 20:36:00)

Re: AHK: Поразрядная ротация

YMP пишет:

oFile.Write(Shifr)   ; записываем

  Я правильно понял, что Raw, не пропущено, а Вы именно так предлагаете записывать? Это же то ж самое, что привычное мне

FileAppend,%str%,1.txt, UTF-16

?

75

Re: AHK: Поразрядная ротация

Я уже думаю, может проще всего перед записью всё преобразовать в банальные 00-FF и записывать как текст?

76 (изменено: YMP, 2014-10-19 21:19:02)

Re: AHK: Поразрядная ротация

Pogodin пишет:

  Я правильно понял, что Raw, не пропущено, а Вы именно так предлагаете записывать? Это же то ж самое, что привычное мне

FileAppend,%str%,1.txt, UTF-16

?

Да, предлагаю использовать строковые чтение и запись, а не бинарные. Так проще. Ну, а использовать объект File, по-моему, удобнее. Как-то единообразнее всё выглядит и проще.

Я уже думаю, может проще всего перед записью всё преобразовать в банальные 00-FF и записывать как текст?

А в чём простота? Лишняя возня скорее.

77

Re: AHK: Поразрядная ротация

YMP пишет:

Так проще. Ну, а использовать объект File, по-моему, удобнее. Как-то единообразнее всё выглядит и проще.

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

#SingleInstance ignore
FileEncoding,UTF-8

FileDelete,1.txt
FileDelete,2.txt

text = 
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)

FileAppend,%text%,1.txt

text := ""
FileRead,text,1.txt

MsgBox, начальный текст из файла:`n%text%

Key1 := "jhhgf3"
Key2 := "rtdvs4"

MsgBox, % "Шифрованный текст:`n" . Shifr := Cipher(text, Key1, Key2)

FileAppend, % Shifr, 2.txt, UTF-16   ; записываем
FileRead, str, 2.txt

MsgBox, % "Расшифровка:`n`n" . text2 := Cipher(str, Key2, Key1)

if( text = text2 )
    MsgBox, Совпадает.
else
    MsgBox, Не совпадает.
    
; =============== Функция шифровки/дешифровки ====================

Cipher(Src, Key1, Key2 = 0)  ; Два последних ключа необязательны.
{
  Loop, 2
  {
    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
}

и

#SingleInstance ignore
FileEncoding,UTF-8

FileDelete,1.txt
FileDelete, 2.txt

text = 
(
1234
12345
1234567
123456789
1234567890
asdfghjqweryuiop
asdfghjqweryuiopweryu
aspdfghjqweryuiodfghjqweryuio
asdfghjqwepryuioryuioryuioryuioryuio
)

FileAppend,%text%,1.txt

text := ""
FileRead,text,1.txt

MsgBox, начальный текст из файла:`n%text%

Key1 := "jhhgf3"
Key2 := "rtdvs4"

MsgBox, % "Шифрованный текст:`n" . Shifr := Cipher(text, Key1, Key2)

oFile := FileOpen("2.txt", "w", "UTF-16")
oFile.Write(Shifr)   ; записываем
oFile.Close()

FileRead, str, 2.txt

MsgBox, % "Расшифровка:`n`n" . text2 := Cipher(str, Key2, Key1)

if( text = text2 )
    MsgBox, Совпадает.
else
    MsgBox, Не совпадает.
    
; =============== Функция шифровки/дешифровки ====================

Cipher(Src, Key1, Key2 = 0)  ; Два последних ключа необязательны.
{
  Loop, 2
  {
    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
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

78

Re: AHK: Поразрядная ротация

teadrinker пишет:

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

Однако сравнение файлов показывает единственную разницу: FileAppend добавляет к переводу строки возврат каретки, а File.Write — нет. Поэтому, если к имени файла добавить *, то разница исчезает.


FileAppend, % Shifr, *2.txt, UTF-16   ; записываем

79

Re: AHK: Поразрядная ротация

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

80

Re: AHK: Поразрядная ротация

YMP пишет:

Поэтому, если к имени файла добавить *, то разница исчезает.

  Колдовство...

81

Re: AHK: Поразрядная ротация

YMP пишет:

Однако сравнение файлов показывает единственную разницу: FileAppend добавляет к переводу строки возврат каретки, а File.Write — нет. Поэтому, если к имени файла добавить *, то разница исчезает.

М-да, точно. В общем, в итоге пришли к тому, что FileAppend и FileRead всё же достаточно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

82 (изменено: Pogodin, 2014-10-20 17:00:07)

Re: AHK: Поразрядная ротация

_