Advertisement
PHP

Creating a Crypter Class with PHP

by

In this article I will explain how to create a PHP Class that will encrypt and decrypt any data with a given password. It is object programmed and uses existing PHP algorithms.


Introduction

Think about what we might need a class like this for? We want to encrypt important data with a password for security reasons. We also want, as already mentioned, to be able to decrypt that data when necessary. Why should you use symmetric algorithms? It's easy; when you're offering a password sent via email or something like that, you need the password to be sent in plaintext. The hash algorithms are not reversible. Once you have hashed a string you can't decipher the original text from the hash.

Maybe you have already heard of MD5? It's not really the best option anymore because it tends to be unsafe. There are databases around the web - that I don't want to mention - that can be used to retrieve the plaintext from a hash simply by typing in the hash into a search box. So you should use something like SHA which was developed by the NSA (National Security Agency). SHA is the abbreviation for Secure Hash Algorithm and is one of the most secure hash algorithms. There are some others as well, such as WHIRLPOOL, PANAMA and RIPEMD, but SHA is currently the secure standard for hashes and is used in numerous applications.


Step 1: Preparation

I think it is important to create an interface. This is because we can always use the methods which are defined in the interface without thinking, when instancing an object of a class, which implements that interface.

When a class implements an interface it has to implement the methods given in that interface, otherwise there will be an error! So here is an example:

  
		interface ICrypter{
			public function Encrypt($data);
			public function Decrypt($data);
		}
	
		class Crypter implements ICrypter{
			public function Encrypt($data){ ... }
			public function Decrypt($data){ ... }
		}

As you can see, the interface instructs the classes which implement ICrypter to have the public function Encrypt with one parameter $data. The public function Decrypt also has the parameter $data. You can try it out; if the class lacks one of the given methods in the interface, you get a fatal error. Here's an example:

Fatal error: Class Crypter contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ICrypter::Decrypt) in C:\www\Nettuts\Crypter\crypter.php on line 32.

Nice error right? So you can be sure that the classes really have the methods!


Step 2: Password for Encryption and Decryption

As I said before, we want to be able to use a specific password for encryption and decryption. This password has to be accessible for the encrypt- and decrypt-function so we will define an instance variable, called key, which is passed to the constructor. The definition of $Key is only needed in the Crypter Class:

 
		private $Key;

However, the definition of the constructor has to be in the interface. Therefore, it is also needed in the class, because we have to implement everything we have defined in the interface. The interface will contain:

 
		public function __construct($Key);

and the class:

 
		public function __construct($Key){ ... }

Now that we know we get a key, we can use it to encrypt and decrypt!


Step 3: Constructor

In the constructor we have to set the key and choose an algorithm. We will use the Blowfish algorithm for this example and use it as a standard value. I will explain a bit more about the symmetric algorithms later in the text, but for simplicity we will use Blowfish. You can change this later if you want to. So we need another instance variable called Algo:

 
		private $Algo;

and the constructor...

 
		public function __construct($Key, $Algo = MCRYPT_BLOWFISH){
			$this->Key = substr($Key, 0, mcrypt_get_key_size($Algo, MCRYPT_MODE_ECB));
			$this->Algo = $Algo;
		}

The length of the key depends on the algorithm and the encryption mode. In this example we will use the ECB mode. You can make this variable like we have already done with the algorithm. We use the substring of the given key with the maximum allowed length. You can get this length with the mcrypt_get_key_size function which requires the algorithm and the encryption mode as parameters.

Now we give our instance variable Key the correct key for the algorithm and assign our instance variable Algo.

So now we have the constructor. As I said previously, you can change the standard value of Algo to any other algorithm that is supported by MCrypt.

List of supported algorithms from php.net:

  • MCRYPT_3DES
  • MCRYPT_ARCFOUR_IV (libmcrypt > 2.4.x only)
  • MCRYPT_ARCFOUR (libmcrypt > 2.4.x only)
  • MCRYPT_BLOWFISH
  • MCRYPT_CAST_128
  • MCRYPT_CAST_256
  • MCRYPT_CRYPT
  • MCRYPT_DES
  • MCRYPT_DES_COMPAT (libmcrypt 2.2.x only)
  • MCRYPT_ENIGMA (libmcrypt > 2.4.x only, alias for MCRYPT_CRYPT)
  • MCRYPT_GOST
  • MCRYPT_IDEA (non-free)
  • MCRYPT_LOKI97 (libmcrypt > 2.4.x only)
  • MCRYPT_MARS (libmcrypt > 2.4.x only, non-free)
  • MCRYPT_PANAMA (libmcrypt > 2.4.x only)
  • MCRYPT_RIJNDAEL_128 (libmcrypt > 2.4.x only)
  • MCRYPT_RIJNDAEL_192 (libmcrypt > 2.4.x only)
  • MCRYPT_RIJNDAEL_256 (libmcrypt > 2.4.x only)
  • MCRYPT_RC2
  • MCRYPT_RC4 (libmcrypt 2.2.x only)
  • MCRYPT_RC6 (libmcrypt > 2.4.x only)
  • MCRYPT_RC6_128 (libmcrypt 2.2.x only)
  • MCRYPT_RC6_192 (libmcrypt 2.2.x only)
  • MCRYPT_RC6_256 (libmcrypt 2.2.x only)
  • MCRYPT_SAFER64
  • MCRYPT_SAFER128
  • MCRYPT_SAFERPLUS (libmcrypt > 2.4.x only)
  • MCRYPT_SERPENT(libmcrypt > 2.4.x only)
  • MCRYPT_SERPENT_128 (libmcrypt 2.2.x only)
  • MCRYPT_SERPENT_192 (libmcrypt 2.2.x only)
  • MCRYPT_SERPENT_256 (libmcrypt 2.2.x only)
  • MCRYPT_SKIPJACK (libmcrypt > 2.4.x only)
  • MCRYPT_TEAN (libmcrypt 2.2.x only)
  • MCRYPT_THREEWAY
  • MCRYPT_TRIPLEDES (libmcrypt > 2.4.x only)
  • MCRYPT_TWOFISH (for older mcrypt 2.x versions, or mcrypt > 2.4.x )
  • MCRYPT_TWOFISH128 (TWOFISHxxx are available in newer 2.x versions, but not in the 2.4.x versions)
  • MCRYPT_TWOFISH192
  • MCRYPT_TWOFISH256
  • MCRYPT_WAKE (libmcrypt > 2.4.x only)
  • MCRYPT_XTEA (libmcrypt > 2.4.x only)

So which one should we use when we want to use the Crypter Class in our products? At the moment AES is the standard of the symmetric algorithms. It is used in many applications, but where is AES? AES was originally published as Rijndael which is listed. It is a really fast, but secure, algorithm and is even fast with 256-Bit key size. My advice is to use MCRYPT_RIJNDAEL_256 for your applications. Just as an example, AES is used in WPA2 which is a security standard for WLAN.


Step 4: Now to the Encryption

First thing to check: is there any data to encrypt? If not, you can go ahead and break the encryption. If you want to use any other encryption modes then you have to add the following code.

 
		$iv_size = mcrypt_get_iv_size($this->Algo, MCRYPT_MODE_ECB);
		$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

This $iv is used for example in CBC, CFB, OFB and in some algorithms in STREAM encryption mode. If the parameter is not passed in these modes, the $iv will be set to '\0'. The next step is to encrypt the data with the simple function mcrypt_encrypt. Here we need our algorithm, the key, the data and an encryption mode. $iv is optional.

 
		$crypt = mcrypt_encrypt($this->Algo, $this->Key, $data, MCRYPT_MODE_ECB, $iv);

Finally encode the encrypted data with base64_encode and trim it before you return it.

 
		return trim(base64_encode($crypt));

We have to base64 encode the encrypted data to get URL-Safe data. This is needed because, if you want to use the encrypted data, for example in a URL, you will have problems with '&' as it is a reserved character specified in the RFC. So you need something like alphanumeric characters - in other words, character that are safe. The base64 encode supplies these safe characters, which is why we're using it. We do not know what will be done with the data after encryption.


Step 5: Decryption is Reversed Encryption

Again we ask the same first question. Is there data? If there is, you have to base64_decode the data as we have previously encoded it with base64_encode.

 
	$crypt = base64_decode($data);

Then the optional part with $iv.

 
			$iv_size = mcrypt_get_iv_size($this->Algo, MCRYPT_MODE_ECB);
			$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);

Decryption with the simple function mcrypt_decrypt. Here we need - nearly - the same parameters. The difference is that the decrypt-function needs to access the crypted data rather than the original data. So here again we use, the algorithm, the key, the crypted data, the encryption mode, and the optional iv.

 
		$decrypt = mcrypt_decrypt($this->Algo, $this->Key, $crypt, MCRYPT_MODE_ECB, $iv);

Finally return the trimmed and decrypted data.

 
		return trim($decrypt);


Examples

Define a global Crypter. In this example we will use RIJNDAEL_256 (AES) with the password "Any password". After instancing you call your functions or methods to test it. Here we call the function foo and the method foo1.

 
		$crypter = new Crypter("Any password", MCRYPT_RIJNDAEL_256);

		foo();
		
		$foo = new Foo();
		$foo->foo1();

You can get your crypter from the Superglobal variable called $GLOBALS. This is an associative array, so you can call all your global variables by the name you defined them with. You can retrieve the $crypter which is defined outside of the foo or foo1 block with $GLOBALS["crypter"]...

 
		function foo(){
			...
			$encrypted = $GLOBALS["crypter"]->Encrypt($data);
			$decrypted = $GLOBALS["crypter"]->Decrypt($encrypted);
			...
		}
		
		class Foo{
			public function foo1(){
				...
				$encrypted = $GLOBALS["crypter"]->Encrypt($data);
				$decrypted = $GLOBALS["crypter"]->Decrypt($encrypted);
				...
			}
		}

Conclusion

Now you have a complete Crypter class and you can crypt and decrypt as many times as you wish! Download the complete source code with a nice example if you do not want to type it in yourself. I hope that you have enjoyed this article.

Related Posts
  • Computer Skills
    Security
    Extreme Security With TrueCryptTruecryptpreview
    In this tutorial I'll show you how to use TrueCrypt to store files on your Mac as securely and secretly as possible. I’ll also show you how to use nested TrueCrypt volumes to keep your secrets safe–even if you are subjected to extortion or torture.Read More…
  • Code
    Web Development
    Securely Handling User's Login CredentialsSecure wide retina preview
    Consider the following tips on how to properly secure your user's login credentials.Read More…
  • Code
    Web Development
    Laravel Unwrapped: Session, Auth and CacheLaravel wide retina preview
    Join me as we learn how to use Laravel's component-based system, Illuminate. Additionally, we'll see how to utilize service providers, Laravel's manager system, the Session, Auth, and Cache components, and the Store, Guard, and Repository libraries.Read More…
  • Code
    iOS SDK
    Securing and Encrypting Data on iOSPs8e2e preview image@2x
    Whether you're creating a mobile application or a web service, keeping sensitive data secure is important and security has become an essential aspect of every software product. In this tutorial, I will show you how to safely store user credentials using the application's keychain and we'll take a look at encrypting and decrypting user data using a third party library.Read More…
  • Computer Skills
    Security
    How to Set Up and Use Password Protected Vaults on a MacPassworddisk2x
    Everyone has some files that they don't want other people to see. They may be important business documents, tax returns, health information or anything else someone would want kept secret. While it's all well and good to have a password on your Mac, if someone gets past that password (and there are ways), or comes across your Mac while it is logged in, they have access to all your files. For that reason, it is worth having a second line of defence; by having your most important files locked away securely except when they are actively in use, you can keep them as safe as possible. In this tutorial I will show you three methods for doing so; making your own solution with Apple's Disc Utility, using the open source TrueCrypt and using AgileBits' Knox.Read More…
  • Code
    PHP
    Validation and Exception Handling: From the UI to the BackendProcedural to oop php retina preview
    Sooner or later in your programming career you will be faced with the dilemma of validation and exception handling. This was the case with me and my team also. A couple or so years ago we reached a point when we had to take architectural actions to accommodate all the exceptional cases our quite large software project needed to handle. Below is a list of practices we came to value and apply when it comes to validation and exception handling.Read More…