..oO(Betikci Boris)
Quote:
>I get bored last night and wrote a script that uses xor for encrypt-
>decrypt, however it woks fine under linux 2.6.25, text and documents
>are ok, but fails on compressed files *.jpg, *.pdf , etc . I didn't
>test script on windows.
>
>Here is the code, please send me your views.
>[...]
There are some logical flaws in the code and I'm wondering if it worked
at all:
* The encrypt_file() function reads the first 12 bytes to check if the
file is already encrypted, but then doesn't jump back to the beginning
of the file when the encryption process starts.
* With bigger files you'll end up with the string 'encrypted_so' being
scattered across the entire file, because your encryption loop may open
and close the target file multiple times and will write that string
before every chunk of 64K.
* These lines
if ($k == sizeof($key))
$k = 0;
$k++;
will cause E_NOTICE errors after the first run of the loop. From there
on the first char of the key will be ignored. Additionally sizeof() is
an alias for count(), which only works on arrays, not on strings. So it
should be something like
$k++;
if ($k == strlen($key)) {
$k = 0;
}
instead.
But IMHO the biggest problem is that you use strlen() on binary data.
This function should not be considered binary-safe! If the Multibyte
extension is enabled, strlen() might be overloaded with mb_strlen().
This means that it tries to work on chars, not on bytes anymore. If you
compare the output of strlen() and filesize() of a small binary file,
you'll most likely get different results. To solve this issue, you could
use a little helper function like this to get the real binary size:
function strSize($string) {
return extension_loaded('mbstring')
? mb_strlen($string, '8bit')
: strlen($string);
}
You should also consider to move the encryption/decryption part to a
seperate function, because the algorithm is the same. With some little
improvements it may look like this:
function codec($fp_r, $fp_w, $key) {
$keySize = strSize($key);
$k = 0;
while (!feof($fp_r)) {
$data = fread($fp_r, 65536);
$result = '';
for ($i = 0, $c = strSize($data); $i < $c; $i++) {
$result .= $data[$i] ^ $key[$k];
$k++;
if ($k == $keySize) {
$k = 0;
}
}
fwrite($fp_w, $result);
}
}
Given these two little helpers, your main functions may now look like
this (I've restructured the code a bit to make it more readable for me):
function encrypt_file($file, $key) {
$fp_r = fopen($file, 'rb');
if (fread($fp_r, 12) == 'encrypted_so') {
fclose($fp_r);
die("file is encrypted! can not be encrypted again!\n");
}
fseek($fp_r, 0);
$fp_w = fopen("{$file}_temp", 'wb');
fwrite($fp_w, 'encrypted_so');
codec($fp_r, $fp_w, $key);
fclose($fp_r);
fclose($fp_w);
unlink($file);
rename("{$file}_temp", $file);
echo "Encryption made successfully!\n";
}
function decrypt_file($file, $key) {
$fp_r = fopen($file, 'rb');
if (fread($fp_r, 12) != 'encrypted_so') {
fclose($fp_r);
die("file is not encrypted! so can not be decrypted..\n");
}
$fp_w = fopen("{$file}_temp", 'wb');
codec($fp_r, $fp_w, $key);
fclose($fp_r);
fclose($fp_w);
unlink($file);
rename("{$file}_temp", $file);
echo "Decryption made successfully!\n";
}
Tested on a small text file, a GIF and an MP3. All worked well.
HTH
Micha