Search code examples
phpencryptionbit-shiftcaesar-cipher

Shift Cipher on numbers in PHP


Im writing a combination of a vigenere and shift cipher in php, where, for characters it uses vigenere table, and for numbers it uses the lenght of the key submitted. Its encrypting just fine , but when i desencrypt it, the numbers just come as ???? or 000s, here's the code for the digits part.

Also, if the lenght of the key is long at makes the number go beyond 10, it will just give me values like ">" or ":"

$str = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1555s";
$key = "aaa";

printf("Text: %s\n", $str);
echo "<br> </br>";
printf("key:  %s\n", $key);

$cod = encipher($str, $key, true); 
$dec = encipher($cod, $key, false); 

echo "<pre> Code:" . $cod .  "</pre>";
echo "<pre> Back:" . $dec .  "</pre>";
function encipher($src, $key, $encoder)
{
    $key = strtoupper($key);
    $src = strtoupper($src);
    $dest = '';

    /* strips out non-letters */
    for($i = 0; $i <= strlen($src); $i++) {
        $char = substr($src, $i, 1);
        if(ctype_upper($char) or ctype_digit($char)) {
            $dest .= $char;
        }
    }

    for($i = 0; $i <= strlen($dest); $i++) {
        $char = substr($dest, $i, 1);
    if(ctype_digit($char)){
        $dest = substr_replace($dest,
                $encoder
                ? $char + strlen($key)
                : $char - strlen($key)
                    , $i, 1);
            }


      if(!ctype_upper($char)) {
            continue;
        }
        $dest = substr_replace($dest,
            chr (
                ord('A') +
                ($encoder
                   ? ord($char) - ord('A') + ord($key[$i % strlen($key)]) - ord('A')
                   : ord($char) - ord($key[$i % strlen($key)]) + 26
                ) % 26
            )
        , $i, 1);
    }

    return $dest;
}

So, the output is this

Code:LOREMIPSUMISSIMPLYDUMMYTEXTOFTHEPRINTINGANDTYPESETTINGINDUSTRYLOREMIPSUMHASBEENTHEINDUSTRYSSTANDARDDUMMYTEXTEVERSINCETHE4888S

Back:LOREMIPSUMISSIMPLYDUMMYTEXTOFTHEPRINTINGANDTYPESETTINGINDUSTRYLOREMIPSUMHASBEENTHEINDUSTRYSSTANDARDDUMMYTEXTEVERSINCETHE����S

But, it should be this

Code:LOREMIPSUMISSIMPLYDUMMYTEXTOFTHEPRINTINGANDTYPESETTINGINDUSTRYLOREMIPSUMHASBEENTHEINDUSTRYSSTANDARDDUMMYTEXTEVERSINCETHE4888S

Back:LOREMIPSUMISSIMPLYDUMMYTEXTOFTHEPRINTINGANDTYPESETTINGINDUSTRYLOREMIPSUMHASBEENTHEINDUSTRYSSTANDARDDUMMYTEXTEVERSINCETHE1555S

EDIT:

Its working now, I changed the code up there, but, if the lenght of the key makes a number go beyound 10, it will time out

Fatal error: Maximum execution time of 30 seconds exceeded


Solution

  • I fixed it by simply creating a circle from 0 to 9, by just picking the last number of the string if its >= 10, and to decrypt use that last number for the array, adding it to 90, so if the number is 5, the auxiliary string will be 95 and subtract the key lenght to it, and just take the last digit of it, so 95-6 = 9.

    enter image description here

    Cycle for the Digits encryption/decryption:

     for ($i = 0; $i <= strlen($dest); $i++) {
                            $char = substr($dest, $i, 1);
                            if (ctype_digit($char)) {
                                $aux = array(9,0);
                                $aux[1]=$char;
                                $dest = substr_replace($dest,
                            $encoder
                            ? str_split($char + strlen($key))[(strlen($char + strlen($key))-1)]
                            : str_split(implode($aux)-strlen($key))[1]
                                        , $i, 1);
                            }