📜 ⬆️ ⬇️

Vigenere cipher modification

Recently, for personal use, it was necessary to use some simple cipher to hide information. Initially I wanted to use the good old Caesar cipher , where each character is replaced by another one shifted by a fixed number of positions (for example, when shifting by one position, we get ARKA-> BSLB). However, in the case of encryption of small amounts of information and in the case of repeated letters in the source text, the cipher is hacked in a matter of seconds (for example, in our case, the shift by unit “LLC BARK” -> “PPP VBSL”). As a result, the choice fell on the Vigenère cipher , which is fairly simple to implement and more resistant to cracking ...



The Vigenere cipher is poly-alphabetic and is a sequence of Caesar ciphers with different shift values. For example, the first character is encoded with a shift of 3, the second - by 5, the third - by 8, etc. The numerical sequence of shift values ​​is memorized using a code word, where the position of the corresponding letter in the original alphabet means the desired shift value. So, for the code word “AVERS”, the first character of our text will be encrypted without a shift (“A” -0), the second - with a shift by 2 (“B” -2) ... the fifth one - with a shift by 18 (“C” -18 ), the sixth - again without a shift (“A”), etc. As a result, for the code word “AVERS” we get “PARUS” -> “PVCDG”.
')
Everything seems to be good, cryptographic resistance has increased, repeated letters no longer pose a danger (“LLC BARK” -> “ORR SSRM”), but another moment appears that is related to the cipher features: the result will always look the same when encoded (“IVANOV” will always "IDEOYAV"). This feature is especially critical for small messages in cases where the length of the code word is equal to the length of frequently repeated moments in the text. If the latter can be successfully fought by increasing the length of the code word, then nothing can be done with the repeatability of the result when encoding the same text.

I found a way out for myself in an additional random first character, more precisely, a digit that performs a dual function. First, it denotes the number of random additional characters to the source text, and secondly, it is the amount of shift of the code word for encoding the rest of the text (“0” - “AVERS”, “1” - “VERSA”, “2” - “ERSAB” etc.). The result is a floating result length (by adding random characters) and different sequences when encrypting identical texts.

For those interested, here are the code in 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; } 


PS Yes, the code is not optimal, but, IMHO, in this form it will be easier on the part to understand it and modify it to fit your needs.

Source: https://habr.com/ru/post/109904/


All Articles