Приглашаем посетить
Толстой (tolstoy-lit.ru)

Section 12.2.  Encryption

Previous
Table of Contents
Next

12.2. Encryption

Practicing the art of encryption , both for data you store locally and for data you send to and from your clients and other data consumers, is not only recommended, but it is a staple requirement for anything done in conjunction with the Internet.

Encryption is undoubtedly the most complicated topic PHP programmers have to face, partially because encryption is inherently complex, and partially because the PHP extension designed to handle encryption seems to have been designed for encryption experts to use, as opposed to normal people!

12.2.1. Encrypting Data

To encrypt data, you need to use seven different functions , which are: mcrypt_module_open( ), mcrypt_create_iv( ), mcrypt_enc_get_iv_size( ), mcrypt_enc_get_key_size( ), mcrypt_generic_init( ), mcrypt_generic( ), mcrypt_generic_deinit( ), and finally, mcrypt_module_close( ).

The easiest way to learn these functions is just to use them, because they accept limited input and give limited output. This script is a good place to start:

    srand((double)microtime( )*1000000 );
    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CFB, '');
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    $ks = mcrypt_enc_get_key_size($td);
    $key = substr(sha1('Your Secret Key Here'), 0, $ks);
    mcrypt_generic_init($td, $key, $iv);
    $ciphertext = mcrypt_generic($td, 'This is very important data');
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    print $iv . "\n";
    print trim($ciphertext) . "\n";

The script starts with the random number generator seeded with a random value, which is important because our initialization vector (or IV, a seed for random encryption and decryption) will be created by calling the random number generator. The first function called is mcrypt_module_open( ), which opens an encryption algorithm for use. It takes four parameters; however, most people will want to leave them as the same values seen in the script because they are more than enough, even in very secure environments.

Moving on, the next function called is mcrypt_create_iv( ), which creates an IV for our encryption. IVs aren't used to make the key any more difficult to guess. Instead, their purpose is to make the plaintext more innocuousa process referred to as whitening, because the goal of the IV is to make your plaintext look more like white noise by randomizing it a little before encryption.

The mcrypt_create_iv( ) function takes two parameters: the size of IV to create and the method to use to create the IV. The first parameter is filled with the return value from mcrypt_enc_get_iv_size( ), which returns the length the IV should be for the encryption algorithm passed in as its only parameter. The second parameter can be one of MCRYPT_RAND, MCRYPT_DEV_RANDOM, or MCRYPT_DEV_URANDOM. The first generates the IV using a software randomizer; the second uses the Unix device /dev/random; and the third uses the Unix device /dev/urandom. For maximum portability, use MCRYPT_RANDit is not as random as the other two, but it will work wherever you put it. If you use MCRYPT_RAND, remember to seed the random number generated with srand( )!

The function returns an IV for the algorithm we selected with mcrypt_module_open( ). Next we call mcrypt_enc_get_key_size( ) to get the maximum key size our algorithm (parameter one) will take, then we create a key for that algorithm using substr( ) and sha1( ). The return value of mcrypt_enc_get_key_size( ) is the largest key this algorithm accepts, so we pass a plaintext key into sha1( ) to get a hashed value, then copy as many characters from it as the algorithm method will accept.

The next two functions, mcrypt_generic_init( ), and mcrypt_generic( ), initialize the encryption engine with the algorithm, IV, and key we selected, then perform the encryption. The first takes three parameters, which are the algorithm resource to use, the IV we created with mcrypt_create_iv( ), and the key we created using sha1( ) and substr( ). Mcrypt_generic takes two parameters, which are the algorithm resource and the data we actually want to encryptit returns the encrypted value, our ciphertext, which we store in $ciphertext.

So, after lots of function calls, we have finally performed encryption with the function mcrypt_generic( ). To end the script, we need to do some clean up, which is where mcrypt_generic_deinit( ) and mcrypt_module_close( ) come inboth take the algorithm resource as their only parameter and clean up the module.

Section 12.2.  Encryption

It's possible to perform encryption using the mcrypt library with fewer functions. Generally speaking, this is not recommended: using an IV and doing things properly ensures the data is secured properly. Please remember that the only thing worse than not being secured is not being secured and thinking you are secured!


To recap, we select an encryption algorithm and block cipher, create an IV to whiten our plaintext a little, create a secret key that encrypts our data, initialize the algorithm to use our IV and key, run the encryption itself to get our ciphertext, then clean up.

12.2.2. Symmetric Decryption

Once you have mastered encryption, decryption is fairly easy, as it shares most of the same concepts. Here is the same script again; this time, it encrypts and then decrypts the information:

    srand((double)microtime( )*1000000 );
    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_CFB, '');
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    $ks = mcrypt_enc_get_key_size($td);
    $key = substr(sha1('Your Secret Key Here'), 0, $ks);

    mcrypt_generic_init($td, $key, $iv);
    $ciphertext = mcrypt_generic($td, 'This is very important data');
    mcrypt_generic_deinit($td);

    mcrypt_generic_init($td, $key, $iv);
    $plaintext = mdecrypt_generic($td, $ciphertext);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    print $iv . "\n";
    print trim($ciphertext) . "\n";
    print trim($plaintext) . "\n";

Note that we actually call mcrypt_generic_deinit( ) and then mcrypt_generic_init( ) immediately afterwardsthis is important for the encryption to work properly, and you must not forget to do this.

Section 12.2.  Encryption

It is crucial that you do not forget to deinit( ) after you encrypt, then call init( ) again when you want to decrypt.


The above scripts use a very strong form of encryption; however, even they can be broken in seconds if someone cracks your keykeep it secret at all costs. Your IV need not be kept secure, but there's no harm in doing so.


Previous
Table of Contents
Next