Rectangle 27 0

php Encrypting Decrypting file with Mcrypt?


It is binary safe and includes authenticated encryption. Since it uses the open source aes crypt file format (.aes) it is fully compatible with other .aes software.

The interface is pretty simple whether you are encrypting or decrypting. You just give it a source file and password.

While Johns answer is good, using base64 encoding just to fix the binary safety issue is overkill and will make your encrypted files 33% larger than the original. Here is my PHP Implementation of the AES Crypt file format which solves all the above issues transparently.

Note
Rectangle 27 0

php Encrypting Decrypting file with Mcrypt?


$key = /* CRYPTOGRAPHIC!!! key */;
$crypt = new Encryption($key);
$encrypted_string = $crypt->encrypt('this is a test');
$decrypted_string = $crypt->decrypt($encrypted_string); // this is a test
<?php

class Encryption
{
    const CIPHER = MCRYPT_RIJNDAEL_128; // Rijndael-128 is AES
    const MODE   = MCRYPT_MODE_CBC;

    /* Cryptographic key of length 16, 24 or 32. NOT a password! */
    private $key;
    public function __construct($key) {
        $this->key = $key;
    }

    public function encrypt($plaintext) {
        $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE);
        $iv = mcrypt_create_iv($ivSize, MCRYPT_DEV_URANDOM);
        $ciphertext = mcrypt_encrypt(self::CIPHER, $this->key, $plaintext, self::MODE, $iv);
        return base64_encode($iv.$ciphertext);
    }

    public function decrypt($ciphertext) {
        $ciphertext = base64_decode($ciphertext);
        $ivSize = mcrypt_get_iv_size(self::CIPHER, self::MODE);
        if (strlen($ciphertext) < $ivSize) {
            throw new Exception('Missing initialization vector');
        }

        $iv = substr($ciphertext, 0, $ivSize);
        $ciphertext = substr($ciphertext, $ivSize);
        $plaintext = mcrypt_decrypt(self::CIPHER, $this->key, $ciphertext, self::MODE, $iv);
        return rtrim($plaintext, "\0");
    }
}
  • This class does not provide authenticated encryption.
  • This class is not safe for use with binary data (which may end in NUL bytes)

"Authenticated encryption is not necessary." Wrong. Super wrong. Authenticated encryption is no longer negotiable.

Can we add a strong disclaimer? Authenticated encryption is absolutely essential to defend against active attackers. There's really no way to negotiate it away unless you cripple your threat model below what the average script kiddie can pull off, which helps approximately no one.

That's correct. I ran this class on text files, and it worked great. For binary files it is necessary to encode the information before encrypting it. If the files are larger than 100MB or so, base64_encode will cause performance issues, so you may want to consider splitting the files into chunks for encrypting. From a security standpoint this isn't an ideal solution because it provides more opportunity for recovering partial plaintext. But, it works.

Try this PHP5 class for encryption using mcrypt. In this case it's using AES encryption. You'll want to change the key for each site you use it on. If you don't use it at least it may guide you on writing your own version of it.

Will this work for binary data such as images?

Note
Rectangle 27 0

php Encrypting Decrypting file with Mcrypt?


Security::rijndael()

CakePHP has a pretty good implementation of rijndael. I'm not posting code directly here because not sure the legal ramifications.

If encoding a file, you will want to base64_encode() before calling this method with 'encrypt', and base64_decode() after calling this method with 'decrypt'

Note
Rectangle 27 0

php Encrypting Decrypting file with Mcrypt?


Further, a great deal of effort has been done to make sure that developers put together cryptographic primitives correctly. As such, instead of Mcrypt, you should be using libsodium for your PHP projects. libsodium is a fork of NaCl. NaCl/libsodium is written to remove a lot of the cryptographic pitfalls that developers find themselves in, such as timing attacks with verification of MAC tags.

Mcrypt is deprecated in PHP 7.1, and libsodim is the preferred way to handle cryptography in PHP.

Using libsodium in your PHP project is easy, and secure. Scott Arciszewski has written an extensive ebook on using libsodium with PHP at https://paragonie.com/book/pecl-libsodium. It's worth the read for anyone doing PHP cryptography.

You should not be using Mcrypt to encrypt/decrypt data. As shown in your question, and in the accepted answer, the data is not authenticated, which means it will fall victim to chosen ciphertext attacks.

Note