Как стать автором
Обновить

Модификация шифра Виженера

Время на прочтение4 мин
Количество просмотров5.1K
Недавно в личных целях понадобилось использовать некий простой шифр для сокрытия информации. Изначально хотел использовать старый добрый шифр Цезаря, где каждый символ заменяется другим, сдвинутым на фиксированное число позиций (например, при сдвиге на одну позицию получаем АРКА -> БСЛБ). Однако, в случае шифрования небольших объемов информации и в случаях наличия в исходном тексте повторяющихся букв шифр взламывается за считанные секунды (например, в нашем случае сдвига на единицу «ООО БАРК» -> «ППП ВБСЛ»). В результате выбор пал на шифр Виженера, достаточно простой в реализации и более стойкий ко взлому…



Шифр Виженера является полиалфавитным и представляет собой последовательность шифров Цезаря с различным значением сдвига. Например, первый символ кодируем со сдвигом на 3, второй — на 5, третий — на 8 и т.д. Числовую последовательность значений сдвига запоминаем с помощью кодового слова, где позиция соответствующей буквы в исходном алфавите будет означать искомое значение сдвига. Так, для кодового слова «АВЕРС» первый символ нашего текста будем шифровать без сдвига («А»-0), второй — со сдвигом на 2 («В»-2)… пятый — со сдвигом на 18 («С»-18), шестой — снова без сдвига («А») и т.д. В результате для кодового слова «АВЕРС» получаем «ПАРУС» -> «ПВХДГ».

Все вроде бы хорошо, криптостойкость повысилась, повторяющиеся буквы уже не представляют опасность («ООО БАРК» -> «ОРУ ССРМ»), однако появляется другой момент, связанный с особенностями шифра: результат всегда будет выглядеть одинаково при кодировании («ИВАНОВ» всегда будет «ИДЕЮАВ»). Особенно критична указанная особенность для малых сообщений и в случаях, когда длина кодового слова равна длине часто повторяющихся моментов в тексте. Если с последним можно успешно бороться увеличивая длину кодового слова, то с повторяемостью результата при кодировании одинакового текста здесь уже ничего не сделать.

Выход для себя я нашел в добавочном случайном первом символе, точнее цифре, выполняющей двойственную функцию. Во-первых обозначает количество случайных добавочных символов к исходному тексту, а во-вторых — это величина сдвига кодового слова для кодирования остального текста («0» — «АВЕРС», «1» — «ВЕРСА», «2» — «ЕРСАВ» и т.д.). В результате получаем плавающую длину результата (за счет добавления случайных символов) и отличающиеся последовательности при шифровании идентичных текстов.

Для интересующихся привожу код на PHP:


function vizhener_encode($text,$kod) // кодирование, простой метод
 { $kod=strtoupper($kod); $string=strtoupper($text); $enc = array(); $dec = array(); 
   $str="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
   for($i=0;$i<strlen($str);$i++)
    { for($j=0;$j<strlen($str);$j++)
       { $ij=$i+$j; if($ij>=strlen($str)) { $ij=$ij-strlen($str); }
	 $enc[$str{$i}][$str{$j}]=$str{$ij};
	 $dec[$str{$i}][$str{$ij}]=$str{$j};
       }
    }
   $pos=0; $result=""; $string=eregi_replace(" ","_",$string);
   for($i=0;$i<strlen($string);$i++)
    { if(!eregi($string{$i},$str)) { $result=$result.$string{$i}; }
      else
       { $result=$result.$enc[$kod{$pos}][$string{$i}]; $pos=$pos+1;
	 if($pos>=strlen($kod)) { $pos=$pos-strlen($kod); } 
       }
    }   
   return $result;
 }

function vizhener_encode_mod($text,$kod) // кодирование, модифицированный метод
 { $kod=strtoupper($kod); $string=strtoupper($text); $enc = array(); $dec = array();  
   $str="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
   $add=mt_rand(1,9); $string=$string;
   for($i=1;$i<=$add;$i++) { $string=$string.$str{mt_rand(0,strlen($str))}; }
   for($i=0;$i<strlen($str);$i++)
    { for($j=0;$j<strlen($str);$j++)
       { $ij=$i+$j; if($ij>=strlen($str)) { $ij=$ij-strlen($str); }
	 $enc[$str{$i}][$str{$j}]=$str{$ij};
         $dec[$str{$i}][$str{$ij}]=$str{$j};
       }
    }
   $pos=0; $result=""; $string=eregi_replace(" ","_",$string);
   $pos=$pos+$add; while($pos>=strlen($kod)) { $pos=$pos-strlen($kod); }
   if($pos<0) { $pos=$pos+strlen($kod); }
   for($i=0;$i<strlen($string);$i++)
    { if(!eregi($string{$i},$str)) { $result=$result.$string{$i}; }
      else
       { $result=$result.$enc[$kod{$pos}][$string{$i}]; $pos=$pos+1;
	 if($pos>=strlen($kod)) { $pos=$pos-strlen($kod); }
       }
    }
   $result=$enc[$kod{0}][$add].$result;
   return $result;
 }

function vizhener_decode($text,$kod) // декодирование, простой метод
 { $kod=strtoupper($kod); $string=strtoupper($text); $enc = array(); $dec = array(); 
   $str="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
   for($i=0;$i<strlen($str);$i++)
    { for($j=0;$j<strlen($str);$j++)
       { $ij=$i+$j; if($ij>=strlen($str)) { $ij=$ij-strlen($str); }
	 $enc[$str{$i}][$str{$j}]=$str{$ij};
	 $dec[$str{$i}][$str{$ij}]=$str{$j};
       }
    }
   $pos=0; $result=""; $string=eregi_replace(" ","_",$string);
   for($i=0;$i<strlen($string);$i++)
    { if(!eregi($string{$i},$str)) { $result=$result.$string{$i}; }
      else
       { $result=$result.$dec[$kod{$pos}][$string{$i}]; $pos=$pos+1;
	 if($pos>=strlen($kod)) { $pos=$pos-strlen($kod); }
       }
    }
   return $result;
 }

function vizhener_decode_mod($text,$kod) // декодирование, модифицированный метод
 { $kod=strtoupper($kod); $string=strtoupper($text); $enc = array(); $dec = array(); 
   $str="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
   for($i=0;$i<strlen($str);$i++)
    { for($j=0;$j<strlen($str);$j++)
       { $ij=$i+$j; if($ij>=strlen($str)) { $ij=$ij-strlen($str); }
	 $enc[$str{$i}][$str{$j}]=$str{$ij};
	 $dec[$str{$i}][$str{$ij}]=$str{$j};
       }
    }
   $pos=0; $result=""; $string=eregi_replace(" ","_",$string);
   $add=$dec[$kod{0}][$string{0}];
   $pos=$pos+$add; while($pos>=strlen($kod)) { $pos=$pos-strlen($kod); }
   if($pos<0) { $pos=$pos+strlen($kod); }
   for($i=1;$i<(strlen($string)-$add);$i++)
    { if(!eregi($string{$i},$str)) { $result=$result.$string{$i}; }
      else
       { $result=$result.$dec[$kod{$pos}][$string{$i}]; $pos=$pos+1;
	 if($pos>=strlen($kod)) { $pos=$pos-strlen($kod); }
       }
    }
   return $result;
 }


P.S. Да, код не оптимален, но, имхо, в таком виде будет проще со стороны разобраться в нем и модифицировать под свои нужды.
Теги:
Хабы:
Всего голосов 14: ↑9 и ↓5+4
Комментарии21

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Innopolis 2025
Иннополис