Pull to refresh

Шифруем файлы в черно-белых изображениях

Reading time6 min
Views3.3K
Привет, %user%! Одним скучным вечером захотелось мне что-то накодить. Шифратор текста — первое, что пришло мне в голову. Но когда он был готов, оказалось, что он может шифровать любые файлы! В данном примере есть ограничение на размер файла. Файлы весом более 200 кб ему скармливать не следует. Писать сам скрипт будем на PHP.


Идея


Шифруем: читаем содержимое файла, преобразуем его в 0 и 1, цифры преобразуем в пиксели и записываем в файл.
Расшифровываем: читаем файл, определяем цвет каждого пикселя, получаем 0 и 1, из них получаем текст и записываем его в файл.

Приступим!


Для начала, напишем несколько служебных функций:
function readln(){
    $stdin = fopen('php://stdin''r'); 
    return trim(fread($stdin2048));
}

function ascii_decrypt($encryptedtext)
{
    $encryptedtext = str_replace(' '''$encryptedtext);
    $encryptedtext = str_replace("\n"''$encryptedtext);
    $encryptedtext = str_replace("\r"''$encryptedtext);

    $blockstack = str_split($encryptedtext8);
    $plaintext = "";
    while(list($key$val= each($blockstack))
    {
        $plaintext .= bin2ascii($val);
    }
    return $plaintext;
}

function ascii_encrypt($plaintext)
{
    $plaintextlength = strlen($plaintext);
    $i=0;
    for($x = 0$x < $plaintextlength$x++)
    {
        $pt .= ascii2bin($plaintext[$x]);
        //$encryptedtext .= " ";
    }
    return $pt;
}

function ascii2bin($char)
{
    $char = decbin(ord($char));
    $char = str_pad($char8'0', STR_PAD_LEFT);
    return $char;
}

function bin2ascii($binary)
{
    $char = substr($binary$x8);
    $char = chr(bindec($char));
    return $char;
}


Поясню.
Функция readln() читает вводимый текст из командной строки. ascii_encrypt() переводит текст в 0 и 1, а ascii_decrypt() выполняет обратное действие. ascii2bin() преобразует символ в последовательность из 8-ми ноликов и единичек, а bin2ascii(), естественно, выполняет обратное действие.

Теперь главное — шифруем и расшифровываем. Пояснять не буду, так как код и так хорошо прокомментирован.

Шифруем

echo "Input file: ";
$fl = readln($fl);

if(file_exists($fl)) $file = stripslashes(file_get_contents($fl)); else die("Input file not found!\n");
//header('Content-Type: image/png');

//Содержимое файла преобразуем в нолики и единицы... 
//И зачем-то переворачиваем)
$e = strrev(ascii_encrypt($file));

////Нехитрый код для вычисления высоты и ширины рисунка
$l = strlen($e);
$h = floor(sqrt($l));
while($l%$h !== 0$h--;
$w = $l/$h;
//Разбиваем всю кашу по одному символу
$wordDot = str_split($e1);

$line = 0;
$column = 0;

$image = imagecreate($w,$h);
$black = imagecolorallocate($image,0,0,0);//Определяем черный цвет
$white = imagecolorallocate($image,255,255,255);//Белый
foreach($wordDot as $val)
    {
        //Если 0, то русуем белую точку, а если 1 - черную
        if($val == 0)   imageline($image,$column,$line,$column,$line,$white);
                else    imageline($image,$column,$line,$column,$line,$black);
        if($column == $w-1) {$line++$column=-1;}
            $column++;
        
    }

//Сохраняем результат
imagepng($image,'./'.$fl.'.png');
imagedestroy($image);


Расшифровываем

echo "Input file: ";
$fly = readln();
if(file_exists($fly)) $image = imagecreatefrompng($fly); else die("File not found!\n");

//Вычисляем ширину и высоту изображения
        $w = imagesx($image);
        $h = imagesy($image);
//B количество пикселей в нем (S =a*b)
        $wh = $w*$h;
        $x = 0;
        $y = 0;

        for($t=0$t < $wh$t++)
            {
//Определяем цвет точки. 
                $rgb = imagecolorat($image$x$y);
                $colors = imagecolorsforindex($image$rgb);
                $cl = $colors['red'].$colors['green'].$colors['blue'];
//Если белый цвет, то ставим 0, а если черный - 1
                if($cl == '255255255'$binary .= '0';
                if($cl == '000'$binary .= '1';
                if($x == $w-1) {$y++$x=-1;}
                    $x++;
            }
//Переворачиваем и преобразовываем в текст
$dt = ascii_decrypt(strrev($binary));
//Записываем в файл
file_put_contents(str_replace('.png'''$fly), $dt);


Запуск


У вас должен быть установлен интерпретатор PHP.
Linux (Unix):
  • chmod +x classic.php
  • ./classic.php encrypt #Зашифровать
  • ./classic.php decrypt #Расшифровать

Windows:
  • path_to_php\php.exe classic.php encript #Зашифровать
  • path_to_php\php.exe classic.php decrypt #Расшифровать


Заключение


Если вам лень собирать весь код по кусочкам, то вот он целиком.

Этот код еще не годится для полноценного шифрования. Туда можно добавить еще пару десятков степеней шифрования: добавление соли, сжатие, преобразование всего в азбуку Морзе или в китайские символы. Это зависит от степени вашей извращенности изощренности. Я работаю над тем, чтобы он мог шифровать большие файлы. В скором времени хочу запустить сервис по шифрованию.
Вот и все, до встречи на Хабре! Заглядывайте на мой блог!

PS. При шифровании исполняемых файлов получается красивая картинка:
XLiveAchiever.asi


MD5Inside.exe


PPS. Расшифруйте это сообщение ;)
Расшифруй, что здесь написано ;)
Tags:
Hubs:
Total votes 42: ↑23 and ↓19+4
Comments24

Articles