In this tutorial you will learn how to encrypt and decrypt data using PHP's Mcrypt functions. The Mcypt library (http://mcrypt.sourceforge.net/), makes encryption/decryption extremely easy to implement. Mcrypt supports a wide variety of encryption mode and algorithms depending on your needs. In this tutorial, I will not cover all of the modes and algorithms that mcrypt is capable of, but rather, I will provide a simple interface for securing information via mcrypt and php. While mcrypt does provide decent encryption, no encryption is unbreakable, so you are forewarned that storing encrypted information in database or similar can still be insecure.
Tutorial Requirements There are very few requirements to get the code in this tutorial to work correctly, they are:
+ Any webserver with PHP 4.x or PHP 5.x installed
+ Mcrypt module either compiled into php or as a php shared module (requires libmcrypt)
Why Use Mcrypt? In comparison to using hashes (one way encryption), such as: md5, sha1, or various other hash algorithms that only allow information to be encrypted for later comparison, Mcrypt allows people to easily encrypt AND decrypt information. The two way encryption that mcrypt provides has a wide array of uses, including, but not limited to:
+ Securing stored confidential information (ie: passwords, credit card numbers, social security numbers, etc)
+ Securing steams of communication (ie: email, server to server communications, application to application communications, etc)
+ Securing files (ie: private keys, secure certificates, etc )
Also, mcrypt supports multiple encryption modes: + ECB (electronic codebook) is suitable for encrypting small amounts of data, such as credit card numbers.
+ CBC (cipher block chaining) is suitable for encrypting large amounts of data, such as files.
+ CFB (cipher feedback) is suitable for encrypting extremely small amount of data, where single bytes need to be encrypted, such as: encrypted streams
Depending on what version of libmcrypt/mcrypt is installed, mcrypt supports a wide variety of encryption algorithms: 3DES
ARCFOUR_IV (libmcrypt > 2.4.x only)
ARCFOUR (libmcrypt > 2.4.x only)
BLOWFISH
CAST_128
CAST_256
CRYPT
DES
DES_COMPAT (libmcrypt 2.2.x only)
ENIGMA (libmcrypt > 2.4.x only, alias for CRYPT)
GOST
IDEA (non-free)
LOKI97 (libmcrypt > 2.4.x only)
MARS (libmcrypt > 2.4.x only, non-free)
PANAMA (libmcrypt > 2.4.x only)
RIJNDAEL_128 (libmcrypt > 2.4.x only)
RIJNDAEL_192 (libmcrypt > 2.4.x only)
RIJNDAEL_256 (libmcrypt > 2.4.x only)
RC2
RC4 (libmcrypt 2.2.x only)
RC6 (libmcrypt > 2.4.x only)
RC6_128 (libmcrypt 2.2.x only)
RC6_192 (libmcrypt 2.2.x only)
RC6_256 (libmcrypt 2.2.x only)
SAFER64
SAFER128
SAFERPLUS (libmcrypt > 2.4.x only)
SERPENT(libmcrypt > 2.4.x only)
SERPENT_128 (libmcrypt 2.2.x only)
SERPENT_192 (libmcrypt 2.2.x only)
SERPENT_256 (libmcrypt 2.2.x only)
SKIPJACK (libmcrypt > 2.4.x only)
TEAN (libmcrypt 2.2.x only)
THREEWAY
TRIPLEDES (libmcrypt > 2.4.x only)
TWOFISH (for older mcrypt 2.x versions, or mcrypt > 2.4.x )
TWOFISH128 (TWOFISHxxx are available in newer 2.x versions, but not in the 2.4.x versions)
TWOFISH192
TWOFISH256
WAKE (libmcrypt > 2.4.x only)
XTEA (libmcrypt > 2.4.x only)
The phpFreaksCrypto Class (PHP4) This is the php4 class that will be doing all of the encrypting/decrypting, you will need to understand some basic object oriented concepts to use it.
PHP Tutorials :
<?php
/*
* phpFreaksCrypto.class.php4 -> phpFreaksCrypto Class (PHP4)
*/
/**
* @author Dustin Whittle
* @version 0.01
*/
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))
{
// tell people trying to access this file directly goodbye...
exit('This file can not be accessed directly...');
}
class phpFreaksCrypto
{
var $td;
// this gets called when class is instantiated
function phpFreaksCrypto($key = 'MyRandomStringThatWillAlwaysBeTheSame', $iv = false, $algorithm = 'tripledes', $mode = 'ecb')
{
if(extension_loaded('mcrypt') === FALSE)
{
$prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
dl($prefix . 'mcrypt.' . PHP_SHLIB_SUFFIX) or die('The Mcrypt module could not be loaded.');
}
if($mode != 'ecb' && $iv === false)
{
/*
the iv must remain the same from encryption to decryption and is usually
passed into the encrypted string in some form, but not always.
*/
die('In order to use encryption modes other then ecb, you must specify a unique and consistent initialization vector.');
}
// set mcrypt mode and cipher
$this->td = mcrypt_module_open($algorithm, '', $mode, '') ;
// Unix has better pseudo random number generator then mcrypt, so if it is available lets use it!
$random_seed = strstr(PHP_OS, "WIN") ? MCRYPT_RAND : MCRYPT_DEV_RANDOM;
// if initialization vector set in constructor use it else, generate from random seed
$iv = ($iv === false) ? mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), $random_seed) : substr($iv, 0, mcrypt_enc_get_iv_size($this->td));
// get the expected key size based on mode and cipher
$expected_key_size = mcrypt_enc_get_key_size($this->td);
// we dont need to know the real key, we just need to be able to confirm a hashed version
$key = substr(md5($key), 0, $expected_key_size);
// initialize mcrypt library with mode/cipher, encryption key, and random initialization vector
mcrypt_generic_init($this->td, $key, $iv);
}
function encrypt($plain_string)
{
/*
encrypt string using mcrypt and then encode any special characters
and then return the encrypted string
*/
return base64_encode(mcrypt_generic($this->td, $plain_string));
}
function decrypt($encrypted_string)
{
/*
remove any special characters then decrypt string using mcrypt and then trim null padding
and then finally return the encrypted string
*/
return trim(mdecrypt_generic($this->td, base64_decode($encrypted_string)));
}
// since php 4 does not have deconstructors, we will need to manually call this function
function __destruct()
{
// shutdown mcrypt
mcrypt_generic_deinit($this->td);
// close mcrypt cipher module
mcrypt_module_close($this->td);
}
}
?>
Usage Example (PHP4) This is a simple usage example which instantiates the class in PHP4 and calls the encrypt/decrypt/__destruct methods.
PHP Tutorials :
<?php
require_once('phpFreaksCrypto.class.php4'); // require the phpFreaksCrypto class
The phpFreaksCrypto Class (PHP5) This is the PHP5 class that will be doing all of the encrypting/decrypting. The only difference in this class is that there are some PHP5 concepts implemented. For example, PHP5 has constructors/deconstructors, so there is no need to create and call separate functions. In addition, there is the concept of visibility applied. Since this is not a tutorial on PHP5, I will not explain these concepts. To see the difference compare the two scripts!
PHP Tutorials :
<?php
/*
* phpFreaksCrypto.class.php5 -> phpFreaksCrypto Class (PHP5)
*/
/**
* @author Dustin Whittle
* @version 0.01
*/
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME']))
{
// tell people trying to access this file directly goodbye...
exit('This file can not be accessed directly...');
}
class phpFreaksCrypto
{
private $td;
// this gets called when class is instantiated
public function __construct($key = 'MyRandomStringThatWillAlwaysBeTheSame', $iv = false, $algorithm = 'tripledes', $mode = 'ecb')
{
if(extension_loaded('mcrypt') === FALSE)
{
$prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
dl($prefix . 'mcrypt.' . PHP_SHLIB_SUFFIX) or die('The Mcrypt module could not be loaded.');
}
if($mode != 'ecb' && $iv === false)
{
/*
the iv must remain the same from encryption to decryption and is usually
passed into the encrypted string in some form, but not always.
*/
die('In order to use encryption modes other then ecb, you must specify a unique and consistent initialization vector.');
}
// set mcrypt mode and cipher
$this->td = mcrypt_module_open($algorithm, '', $mode, '') ;
// Unix has better pseudo random number generator then mcrypt, so if it is available lets use it!
$random_seed = strstr(PHP_OS, "WIN") ? MCRYPT_RAND : MCRYPT_DEV_RANDOM;
// if initialization vector set in constructor use it else, generate from random seed
$iv = ($iv === false) ? mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), $random_seed) : substr($iv, 0, mcrypt_enc_get_iv_size($this->td));
// get the expected key size based on mode and cipher
$expected_key_size = mcrypt_enc_get_key_size($this->td);
// we dont need to know the real key, we just need to be able to confirm a hashed version
$key = substr(md5($key), 0, $expected_key_size);
// initialize mcrypt library with mode/cipher, encryption key, and random initialization vector
mcrypt_generic_init($this->td, $key, $iv);
}
public function encrypt($plain_string)
{
/*
encrypt string using mcrypt and then encode any special characters
and then return the encrypted string
*/
return base64_encode(mcrypt_generic($this->td, $plain_string));
}
public function decrypt($encrypted_string)
{
/*
remove any special characters then decrypt string using mcrypt and then trim null padding
and then finally return the encrypted string
*/
return trim(mdecrypt_generic($this->td, base64_decode($encrypted_string)));
}
// this function gets called when php garbage collection destroys the object
public function __destruct()
{
// shutdown mcrypt
mcrypt_generic_deinit($this->td);
// close mcrypt cipher module
mcrypt_module_close($this->td);
}
}
?>
Usage Example (PHP5) This is a simple usage example which instantiates the class in PHP5 and calls the encrypt/decrypt methods.
PHP Tutorials :
<?php
require_once('phpFreaksCrypto.class.php5'); // require the phpFreaksCrypto class
That looked pretty, but what is happening??? Ok, so lets break it down step by step! I will be using the PHP5 version of my code to break the process down step by step. I am doing this because I believe anyone reading this tutorial should be in the process of migrating to PHP5 and learning OOP concepts.
PHP Tutorials :
<?
// this gets called when class is instantiated
public function __construct($key = 'MyRandomStringThatWillAlwaysBeTheSame', $iv = false, $algorithm = 'tripledes', $mode = 'ecb')
{
if(extension_loaded('mcrypt') === FALSE)
{
$prefix = (PHP_SHLIB_SUFFIX == 'dll') ? 'php_' : '';
dl($prefix . 'mcrypt.' . PHP_SHLIB_SUFFIX) or die('The Mcrypt module could not be loaded.');
}
if($mode != 'ecb' && $iv === false)
{
/*
the iv must remain the same from encyption to decryption and is usually
passed into the encrypted string in some form, but not always.
*/
die('In order to use encryption modes other then ecb, you must specify a unique and consistent initialization vector.');
}
// set mcrypt mode and cipher
$this->td = mcrypt_module_open($algorithm, '', $mode, '') ;
// Unix has better pseudo random number generator then mcrypt, so if it is available lets use it!
$random_seed = strstr(PHP_OS, "WIN") ? MCRYPT_RAND : MCRYPT_DEV_RANDOM;
// if initialization vector set in constructor use it else, generate from random seed
$iv = ($iv === false) ? mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), $random_seed) : substr($iv, 0, mcrypt_enc_get_iv_size($this->td));
// get the expected key size based on mode and cipher
$expected_key_size = mcrypt_enc_get_key_size($this->td);
// we dont need to know the real key, we just need to be able to confirm a hashed version
$key = substr(md5($key), 0, $expected_key_size);
// initialize mcrypt library with mode/cipher, encryption key, and random initialization vector
mcrypt_generic_init($this->td, $key, $iv);
}
?>
This is the class constructor: this is the function that is executed when ever you instantiate the class ($crypto = new phpFreaksCrypto();). This function basically deterimes whether mcrypt is available, and sets the algorithm, mode, and key used to encrypt the data.
PHP Tutorials :
<?
public function encrypt($plain_string)
{
/*
encrypt string using mcrypt and then encode any special characters
and then return the encrypted string
*/
return base64_encode(mcrypt_generic($this->td, $plain_string));
}
public function decrypt($encrypted_string)
{
/*
remove any special characters then decrypt string using mcrypt and then trim null padding
and then finally return the encrypted string
*/
return trim(mdecrypt_generic($this->td, base64_decode($encrypted_string)));
}
?>
This is where the mcrypt magic happens! When either function, (encrypt or decrypt) is called, the functions will return the encrypted/decrypted.
PHP Tutorials :
<?
// this function gets called when php garbage collection destroys the object
public function __destruct()
{
// shutdown mcrypt
mcrypt_generic_deinit($this->td);
// close mcrypt cipher module
mcrypt_module_close($this->td);
}
?>
This is the deconstructor: the purpose is to deconstruct the class when you are done using it. In this case, its function is to close the mcrypt module once we are done encrypting/decrypting the data.
Making my class work for you! (PHP4)
PHP Tutorials :
<?php
require_once('phpFreaksCrypto.class.php4'); // require the phpFreaksCrypto class
$crypto = new phpFreaksCrypto(); // instantiate the class
$the_string_to_be_encrypted = 'blah.blah.blah';
$the_string_that_is_encrypted = $crypto->encrypt($the_string_to_be_encrypted);
$the_encrypted_string_decrypted = $crypto->decrypt($the_string_that_is_encrypted);
$crypto->__destruct();
<?php
require_once('phpFreaksCrypto.class.php5'); // require the phpFreaksCrypto class
$the_string_to_be_encrypted = 'blah.blah.blah';
$crypto = new phpFreaksCrypto(); // instantiate the class
$the_string_that_is_encrypted = $crypto->encrypt($the_string_to_be_encrypted);
$the_encrypted_string_decrypted = $crypto->decrypt($the_string_that_is_encrypted);
This should give you a good start on encrypting and decrypting information with mcrypt and PHP4/5. Thanks for reading my tutorial on mcrypt and PHP, I hope it helps! If it did make sure to post a nice comment, otherwise... :) Good luck!