1

I'm surprised that I didn't find any code snippet, advice or tutorial in the web that explains how to encrypt a file using just standard php components.

So I'm asking your advice: how to encrypt/decrypt files using just mcrypt and php standard functions? I do not have the option to use gnupg. No, actually, my question is: how to do the above without messing up my files? Because I'm already encrypting/decrypting the hell out of these files (with mcrypt/AES), and it works well for jpegs, PDF, some .doc files and interestingly password-secured .docx files. It does not work for non-secured .docx files and numerous other filetypes.

My current code is this. Basically, I really just open the file, whisk the data around with mcrypt/AES, and write it on server/let user download it.

To encode after upload:

// using codeigniter's encryption library, which uses mcrypt and the AES cypher
$this->load->library('encrypt');
$pathandname = $config['upload_path'].$output['content'][$a]['file_name']; 
$theFile = file_get_contents($pathandname);
$fh = fopen($pathandname,'w');
fwrite($fh,$this->encrypt->encode($theFile));
fclose($fh); 

To decode & download:

$this->load->library('encrypt');
$pathandname = $filelocation.$results[0]['encryptedfile']; 
$theFile = file_get_contents($pathandname);
$decrypted = $this->encrypt->decode($theFile);
force_download($filename, $decrypted); // a codeigniter function to force download via headers
3
  • What exactly is the problem? Does your current approach not work? Or are you interested in how to do it without CodeIgniter? If the latter, why not just read the relevant sources? Commented Jul 30, 2012 at 6:02
  • No, I want to know how to use essentially this method. But decrypted file Commented Jul 30, 2012 at 8:25
  • Don't use the outdated CodeIgniter 2 encrypt library any more, use CodeIgniter 3's Encryption library instead. Encrypt was brittle, Encryption is secure. Commented Aug 11, 2015 at 23:33

1 Answer 1

2

how to encrypt/decrypt files using just mcrypt and php standard functions?

Well, you don't want to use mcrypt. You want to use sodium these days.

Encrypting a File with Sodium (PHP 7.2+, PECL ext/sodium, or sodium_compat)

The relevant API you're looking for is crypto_secretstream.

const CUSTOM_CHUNK_SIZE = 8192;

/**
 * @ref https://stackoverflow.com/q/11716047
 */
function encryptFile(string $inputFilename, string $outputFilename, string $key): bool
{
    $iFP = fopen($inputFilename, 'rb');
    $oFP = fopen($outputFilename, 'wb');

    [$state, $header] = sodium_crypto_secretstream_xchacha20poly1305_init_push($key);

    fwrite($oFP, $header, 24); // Write the header first:
    $size = fstat($iFP)['size'];
    for ($pos = 0; $pos < $size; $pos += CUSTOM_CHUNK_SIZE) {
        $chunk = fread($iFP, CUSTOM_CHUNK_SIZE);
        $encrypted = sodium_crypto_secretstream_xchacha20poly1305_push($state, $chunk);
        fwrite($oFP, $encrypted, CUSTOM_CHUNK_SIZE + 17);
        sodium_memzero($chunk);
    }

    fclose($iFP);
    fclose($oFP);
    return true;
}

Decryption looks like this:

/**
 * @ref https://stackoverflow.com/q/11716047
 */
function decryptFile(string $inputFilename, string $outputFilename, string $key): bool
{
    $iFP = fopen($inputFilename, 'rb');
    $oFP = fopen($outputFilename, 'wb');

    $header = fread($iFP, 24);
    $state = sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $key);
    $size = fstat($iFP)['size'];
    $readChunkSize = CUSTOM_CHUNK_SIZE + 17;
    for ($pos = 24; $pos < $size; $pos += $readChunkSize) {
        $chunk = fread($iFP, $readChunkSize);
        [$plain, $tag] = sodium_crypto_secretstream_xchacha20poly1305_pull($state, $chunk);
        fwrite($oFP, $plain, CUSTOM_CHUNK_SIZE);
        sodium_memzero($plain);
    }
    fclose($iFP);
    fclose($oFP);
    return true;
}

Using the two functions together:

$key = random_bytes(32);
encryptFile('input.txt', 'cipher.txt', $key);
decryptFile('cipher.txt', 'decrypt.txt', $key);
Sign up to request clarification or add additional context in comments.

1 Comment

Could you explain a bit on the key parameter and what values it takes? And when decrypting you need the same key correct?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.