вторник, 23 августа 2011 г.

Симметричное шифрование php

Понадобилось мне зашифровать свой скрипт. Что бы он работал только если к неу обращаюсь я,
скрипт должен был брать куку и расшифровывть с помощью нее свое тело, после чего все отправлялось в eval. Но оказалось, что в арсенале php нет функции симметричного шифрования (позднее я узнал о mcrypt_ecb, так что всё, что написано ниже, это велосипед). Пришлось писать ее самому. Шифровать я стал с помощью xor по ключу. Получилась у меня вот такая вот функция.

     function xor_it($str,$key)
    {
        $code='';
        for($i=0,$y=0;$i<strlen($str);$i++,$y++)
        {
            if($y==strlen($key)) $y=0;
            $code.=chr(ord(substr($str,$i,1))^ord(substr($key,$y,1)));
        }
        return $code;
    }

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


Вот сама функция:

function cypher($code,$cookie_name,$cookie_key)
{
    function xor_it($str,$key)
    {
        $code='';
        for($i=0,$y=0;$i<strlen($str);$i++,$y++)
        {
            if($y==strlen($key)) $y=0;
            $code.=chr(ord(substr($str,$i,1))^ord(substr($key,$y,1)));
        }
        return $code;
    }

    function pack_it($code)
    {
        return base64_encode(gzdeflate($code));
    }

    function add_protection($code,$checksum,$salt)
    {
        return '/*'.$salt.'*/$i=get_included_files();$s=$i[0];if(filesize($s)=='.$checksum.' && sizeof($i)==1){'.$code.'}else{unlink($s);die('!');}';
    }

    function insert_body($base64_code,$cookie_name)
    {
        return '<?php function x($s,$k){$c=\'\';for($i=0,$y=0;$i<strlen($s);$i++,$y++){if($y==strlen($k))$y=0;$c.=chr(ord(substr($s,$i,1))^ord(substr($k,$y,1)));}return $c;}if(isset($_COOKIE[\''.$cookie_name.'\'])){$k=$_COOKIE[\''.$cookie_name.'\'];$l=floor(strlen($k) / 2);$k1=substr($k,0,$l);$k2=substr($k,$l);$s=gzinflate(base64_decode(\''.$base64_code.'\'));eval(x(x($s,$k1),$k2));}?>';
    }
   
   
   
   
    $code_length=-1;
   
    $compiled_code='';
    $i=0;
    $salt='';
   
    // разбиваем ключ на 2.. хотелось все таки что бы ключ состоял минимум из 2х символов
    $key_len=strlen($cookie_key);
    $key1_len=floor($key_len / 2);
   
    $cookie_key1=substr($cookie_key, 0,$key1_len);
    $cookie_key2=substr($cookie_key, $key1_len);
   
    while($code_length!=strlen($compiled_code))
    {
        if($i>5) // если итераций больше, чем 5, значит надо добавиль 1 символ к коду. это нужно в ситуации, когда изменение символа влияет на длину кода после паковки
        {
            $salt.=chr(rand(0,255));
            $i=0;
        }
       
        $code_length=strlen($compiled_code);    //запоминаем длину кода
        $compiled_code=add_protection($code,$code_length,$salt); // добавляем в код проверку длины
        $compiled_code=xor_it($compiled_code,$cookie_key1); // ксорим по первому ключу
        $compiled_code=xor_it($compiled_code,$cookie_key2); // ксорим по второму ключу
        $compiled_code=pack_it($compiled_code); // пакуем
        $compiled_code=insert_body($compiled_code,$cookie_name); // вставляем код распаковки и запуска
       
        $i++;
    }
   
    return $compiled_code;
}

1 комментарий:

  1. Оказалось, что в php все таки есть функция для симметричного шифрования.

    mcrypt_ecb()

    Так что я написал очередной велосипед

    ОтветитьУдалить