Professional PHP Programming - Using Cryptography (
Page 6 of 9 )
In
PHP, cryptography is mostly used for encrypting information and generating
checksum or digests. Using cryptography can provide a lot of added security when
done right, but it can also give a false feeling of security.
This
paragraph can only give you some ideas on the use of cryptography. If you really
want to get your hands dirty, you should consult some good information on
cryptography. The standard work on cryptography is Bruce Schneier’s Applied
Cryptography, which is both very thorough and surprisingly readable. His website
(
www.counterpane.com/labs.html)
is also a good starting point for finding cryptographic information on the
Internet.
In PHP most of the cryptographic functions are provides
by the mcrypt (
hq.hellug.gr/~mcrypt/)
and mhash (
www.schumann.cx/mhash/)
libraries. You need to install these libraries on your system and configure PHP
to use them using the --with-mcrypt and --with-hash options.
When
compiling PHP with mcrypt support it is possible you will run into compilation
problems. The compiler will start complaining about RC2 (and other things) not
being declared. This is caused by the fact that the file functions/mcrypt.c in
PHP versions 3.0.12 and older is not completely in-sync with current releases of
the mcrypt library. The preferred way of fixing this would be upgrading to PHP
version 3.0.13. Another way to fix this would be to get a newer version of
mcrypt.c from the CVS repository. You can do this by following this URL:
http://cvs.php.net/cvsweb.cgi/functions/mcrypt.c?rev=1.11Using
EncryptionThere are essentially two types of cryptography: public key
and secret key. Sometimes the terms asymmetric and symmetric are
used.
Public key cryptography can be called asymmetric, because the
keys for encrypting and decrypting a message are not the same: you publish the
public key and keep your private key a secret. After you have published your
public key, people can send you messages only you can read. To do this, they
encrypt the messages with your public key. To decrypt the message one would need
the private key. Since you are the only one who has access to this key, you are
the only one who can read this message. You can also use your private key to
sign messages. People can use your public key to verify that you have written a
message. Such a digital signature could be used in court to prove someone sent
an email message. The PGP (Pretty Good Privacy) and GPG (GNU Privacy Guard, the
free alternative to PGP) software can be used with PHP to do public key
cryptography. You can find more information about PGP and GPG at
www.pgp.com and
www.gnupg.org. The problem with public key
cryptography is that it is rather slow and the keys are huge (usually 512 to
2048 bits).
Secret key cryptography can be called symmetric because
the same key is used for encrypting and decrypting data. This is the reason why
you need to keep the key absolutely safe. In fact, in programs such as PGP and
GPG public key cryptography is mostly used for signing messages and sending
secret keys in a secure fashion. The actual encryption of the message is done
with secret key cryptography. As noted before, secret key cryptography is much
faster and uses comparatively small keys (usually 40 – 128
bits).
If you have a need for encryption in your application, you
will probably want to use secret cryptography. There is a whole range of
algorithms to choose from: DES, TripleDES, Blowfish, IDEA and RC5, these are
only a few. It is important to know that some algorithms are considered insecure
(such as DES and RC2), while others are considered to be very secure (Blowfish,
RC5 and IDEA for example). The security supplied by the host algorithm depends
on the key size. Not very long ago, a group PCs connected via the Internet (in
effect creating a very fast supercomputer) decrypted a message that had been
encrypted with the RC5 algorithm using a 56-bit key in less than two days (
www.distributed.net). If the message had
been encrypted with a 128-bit key, this would have been impossible. Simply said,
encrypting a message with a 41-bit key is twice as secure as encrypting it with
a 40-bit key. In practice it is more complex than this, but this should make it
clear how much more secure than a 128-bit key is. In PHP, encryption will mostly
be used to exchange information between two webservers or between a webserver
and a browser in a secure way.
What may be confusing is the fact
that most encryption algorithms (or ciphers) can be run in several modes.
Encryption algorithms can be used in four different modes:
ECB,
Electronic Code BookECB mode is best used for encrypting small pieces of
data that contain of which the contents are mostly random (such as other
encryption keys). Because of the way ECB mode works it is probably safer to
avoid using this mode, unless have a good reason to use ECB mode. You should use
CBC mode, since that mode is considerably safer. With ECB mode, each block of
data (you can get the size of a block with the mcrypt_get_block_size function)
is separately encrypted.
CBC, Cipher Block ChainingCBC
mode is probably the mode you will use most often. If you don’t exactly know
what mode to use, use this one.
CFB, Cipher FeedbackThis is
meant for encrypting byte streams. You probably will not need to use this
mode.
OFB, Output FeedbackThe use of the OFB mode is similar
to CFB mode. You probably will not need OFB mode.
Below is an example of
the use of the mcrypt functions. This example uses encryption in CBC mode.
# $data is the array that contains the data that should be encrypted
$encrypteddata = mcrypt_cbc(MCRYPT_TripleDES, "Secret key",
serialize($data), MCRYPT_ENCRYPT);
$encrypteddata = bin2hex($encrypteddata);
$encrypteddata now contains an encrypted version of the
array. The extra bin2hex step is necessary because mcrypt_ecb outputs binary
data. You will need to use bin2hex, urlencode or another, similar function
before you can use it in a cookie or a form variable. You decrypt the data with
the same process in reverse.
$encrypteddata = hex2bin($encrypteddata);
$data = unserialize(mcrypt_cbc(MCRYPT_TripleDES, "Secret key”,
$encrypteddata, MCRYPT_DECRYPT));
# $data is the array that contains the decrypted data
For the CBC, CFB and OFB mode you can also specify an
initialization vector (IV). This adds some extra security. Both sides need to
have the same IV. If the decrypting side does not have the correct IV, the data
cannot be decrypted. You could generate an IV from a password, as shown below.
$cipher = MCRYPT_IDEA;
$block_size = mcrypt_get_block_size($cipher);
$iv = mcrypt_create_iv($block_size, MCRYPT_DEV_RANDOM);
$encrypteddata = mcrypt_cbc($cipher, "Secret key", $data,
MCRYPT_ENCRYPT, $iv);
(You may need to use MCRYPT_RAND instead of MCRYPT_DEV_RANDOM
on some servers. If you do, please do not forget to initialize the random
generator.)
Note that storing data on your server is probably not going
to add any security. The reason for that is the fact that you will need to store
the key on the same server, effectively defeating any benefits storing data in
an encrypted form had.
Using Hash FunctionsMost encryption
algorithms can also be used to generate a hash or digest. The most well known
example of a hash is probably a CRC value, used by compression programs (such as
ARJ or GZIP) to check whether the archive was damaged or not. The hash of a
piece of data can uniquely identify that piece of data.
Hashes are often
used for storing passwords. If you store the hash of a password, you have a away
of verifying a password when someone logs in without having to store the actual
passwords on your server. For instance, the htpasswd program that comes with
Apache generates a password file that contains hashes of the passwords you give
it. It is very difficult, almost impossible, to generate a working password from
a hash of that password.
In PHP scripts, you can use the crypt function
to generate a hash from a password. If you need to generate a hash of a much
larger piece of data, you should use the mhash module. In order to use the mhash
function PHP needs to be compiled with mhash support. Unlike the mcrypt module
the mhash module should compile without any problems.
Below is an example
of using mhash to generate the 32-bit CRC of a piece of data.
$crc32 = bin2hex(mhash(MHASH_CRC32, "This is a test"));
The call to bin2hex is necessary because mhash outputs
binary data, just like the mcrypt functions.
©1998 Wrox Press Limited, US and UK.