Подход к созданию трудноанализируемых шифров

       

Расшифровка


// обратный ход                                                                                          (3.8)-1

prev = 0;

для i от k до 1

{

          next = сигнатура(prev, ai);

          ai = f

-1(prev, ai);

          prev = next;

}

// прямой ход                                                                                             (3.7)-1

prev = 0;

для i от 1 до k

{



          next = сигнатура(prev, ai);

          ai = f

-1(prev, ai);

          prev = next;

}

// обратный ход                                                                                          (3.6)-1

prev = 0;

для i от k до 1

{

          ai = f

-1(prev, ai);

          prev = сигнатура(prev, ai);

}

// прямой ход                                                                                             (3.5)-1

prev = 0;

для i от 1 до k

{

          ai = f

-1(prev, ai);

          prev = сигнатура(prev, ai);

}

Одной из ранних идей преобразований подобного рода была такая: текст разбивается на две половинки, вычисляется сигнатура первой половины и с помощью этой сигнатуры преобразуется вторая половина, затем наоборот. Каждая из этих половинок опять разбивается на две, и преобразование повторяется рекурсивно, пока длина половинки не станет меньше одного бита (или байта). Время такого преобразования – порядка двоичного логарифма от длины последовательности.

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

Как можно было заметить, преобразование осуществляется без какого-либо привлечения ключа, и имеет место однозначное соответствие исходной и преобразованной последовательности. Изменив вид функции на f(сигнатураi, gi, ai), где g – псевдослучайная последовательность, сгенерированная на основе ключа (или сам ключ, но это снизит криптостойкость), получим зависимость преобразованной последовательности от ключа. Для каждого из преобразований можно использовать различные участки гаммы. Причём из вышеописанного следует то, что малейшее изменение ключа приведёт к глобальному изменению всей преобразованной последовательности.


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

Такое преобразование уже не назовёшь гаммированием с обратной связью, как это описано в [1], это уже скорее свёртка.

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

Данный алгоритм можно применить для потокового шифрования данных. Поскольку конечная часть последовательности в реальном времени недоступна, преобразования (3.6) и (3.8) следует исключить, а преобразования (3.5) и (3.7) объеденить. С одной стороны это повлияет на криптостойкость, поскольку нет влияния последующих битов на предыдущие, но с другой стороны конечная часть последовательности также недоступна для криптоанализа. Если процесс передачи данных допускает буферизацию хотя бы нескольких бит, то преобразования (3.6) и (3.8) можно модифицировать таким образом, чтобы они осуществлялись в пределах буфера. Следует предусмотреть процесс восстановления сигнатур в случае утери или искажения части сообщения, но это уже выходит за рамки статьи. Простейший способ – установка сигнатур в начальные (константные или определяемые по некоторому закону) значения после прохождения определённых объёмов данных и вставка синхронизирующей метки в последовательность. Выглядеть всё это будет приблизительно так:

// зашифровка

prev = prev2 = 0;

пока(не конец последовательности)

{

          next = сигнатура(prev, ai);

          ai = f(prev, gi, ai);

          prev = next;

          ai = f(prev2, g’i, ai);

          prev2 = сигнатура(prev2, ai);

}

// расшифровка

prev = prev2 = 0;

пока(не конец последовательности)

{

          next2 = сигнатура(prev2, ai);

          ai = f

-1(prev2, g’i, ai);

          prev2 = next2;

          ai = f

-1(prev, gi, ai);

          prev = сигнатура(prev, ai);

}


Содержание раздела