More Books
PHP 5 Unleashed
PHP 5 Unleashed
Table of Contents
Copyright
Lead Author
Contributing Authors
Acknowledgments
We Want to Hear from You!
Reader Services
Introduction
Organization of the Book
Part I. Working with PHP for General Web Development
Chapter 1. Basic PHP Development
How PHP Scripts Work
Basic PHP Syntax
Basic PHP Data Types
Variable Manipulation
Control Structures
User-Defined Functions
Dynamic Variables and Functions
Multiple File PHP Scripts
References
Strings in PHP
Comparing Strings
Advanced String Comparison
Search and Replacement
Formatting Strings
Strings and Locales
Formatting Date and Time Values
Summary
Chapter 2. Arrays
Basic Arrays
Implementing Arrays
More Array Materials
Chapter 3. Regular Expressions
The Basics of Regular Expressions
Limitations of the Basic Syntax
POSIX Regular Expressions
Perl-Compatible Regular Expressions (PCRE)
PCRE Modifiers
A Few Final Words
Chapter 4. Working with Forms in PHP
HTML Forms 101
Working with Form Submissions in PHP
Summary
Chapter 5. Advanced Form Techniques
Data Manipulation and Conversion
Form Data Integrity
Form Processing
Summary
Chapter 6. Persistent Data Using Sessions and Cookies
HTTP Cookies
PHP Sessions
Advanced Sessions
Summary
Chapter 7. Using Templates
The What and Why of Templates
The Smarty Template Engine
Summary
Part II. Advanced Web Development
Chapter 8. PEAR
What Is PEAR?
Getting and Installing PEAR
Using the PEAR Package Manager
Using the PEAR Website
Using PEAR Packages in Applications
Summary
Reference
Chapter 9. XSLT and Other XML Concerns
Relating XML to HTML
Using XSLT to Describe HTML Output Using XML Input
PHP4 and XSLT Using the DOM XML Module
PHP4 and XSLT Using the XSLT Module
PHP5 and XSLT
Accessing XML Data Using SimpleXML
Generating XML Documents Using PHP
Summary
References
Chapter 10. Debugging and Optimizations
Debugging Your PHP Scripts
Optimizing Your PHP Scripts
Summary
Chapter 11. User Authentication
Authenticating Users in PHP
Securing PHP Code
Summary
Chapter 12. Data Encryption
Shared Secret Versus Public Key
Shared Secret Algorithms
Public Key Cryptography
Using Public Keys in PHP
Summary
Chapter 13. Object-Oriented Programming in PHP
Why Objects?
Creating Basic Classes
Advanced Classes
Special Methods
Class Autoloading
Object Serialization
Exceptions
Iterators
Summary
Chapter 14. Error Handling
The PHP Error-Handling Model
What to Do About Errors
The Default Error Handler
Error Suppression
Custom Error Handlers
Causing Errors
Putting It All Together
Summary
Chapter 15. Working with HTML/XHTML Using Tidy
Introduction
Basic Tidy Usage
Tidy Configuration Options
Using the Tidy Parser
Applications of Tidy
Summary
Chapter 16. Writing Email in PHP
The MIME Protocol
Implementing MIME Email in PHP
Summary
Part III. Building Applications in PHP
Chapter 17. Using PHP for Console Scripting
Core CLI Differences
Working with PHP CLI
CLI Tools and Extensions
Summary
Chapter 18. SOAP and PHP
What Are Web Services?
Installation
Creating Web Services
Consuming Web Services
Looking for Web Services
Summary
Chapter 19. Building WAP-Enabled Websites
What Is WAP?
System Requirements
Introduction to WML
Serving WAP Content
Sample Applications
Summary
Part IV. I/O, System Calls, and PHP
Chapter 20. Working with the File System
Working with Files in PHP
File Permissions
File Access Support Functions
Summary
Chapter 21. Network I/O
DNS/Reverse DNS Lookups
Socket Programming
Network Helper Functions
Summary
Chapter 22. Accessing the Underlying OS from PHP
Introduction
Unix-Specific OS Functionality
Platform-Independent System Functions
A Brief Note About Security
Summary
Part V. Working with Data in PHP
Chapter 23. Introduction to Databases
Using the MySQL Client
Basic MySQL Usage
Summary
Chapter 24. Using MySQL with PHP
Performing Queries from PHP
A MySQLi Session Handler
What Is a Custom Session Handler?
Summary
Chapter 25. Using SQLite with PHP
What Makes SQLite Unique?
Basic SQLite Functionality
Working with PHP UDFs in SQLite
Odds and Ends
Summary
Chapter 26. PHP's dba Functions
Preparations and Settings
Creating a File-Based Database
Writing Data
Reading Data
Sample Application
Conclusion
Part VI. Graphical Output with PHP
Chapter 27. Working with Images
Basic Image Creation Using GD
Using the PHP/GD Drawing Functions
Working with Colors and Brushes
Using Fonts and Printing Strings
General Image Manipulation
Other Graphics Functions
Summary
Chapter 28. Printable Document Generation
A Note Regarding the Examples in This Chapter
Generating Dynamic RTF Documents
Generating Dynamic PDF Documents
Related Resources
Part VII. Appendixes
Appendix A. Installing PHP5 and MySQL
Installing PHP5
Installing MySQL and PHP Modules
Installing PEAR
Appendix B. HTTP Reference
What Is HTTP?
PHP Programming Libraries for HTTP Work
Understanding an HTTP Transaction
HTTP Client Methods
What Comes Back: Server Response Codes
HTTP Headers
Encoding
Identifying Clients and Servers
The "Referer"
Fetching Content from an HTTP Source
Media Types
Cookies: Preserving State and a Tasty Treat
Security and Authorization
Client-Side Caching of HTTP Content
Appendix C. Migrating Applications from PHP4 to PHP5
Configuration
Object-Oriented Programming (OOP)
New Behavior of Functions
Further Reading
Appendix D. Good Programming Techniques and Performance Issues
Common Style Mistakes
Common Security Concerns
Style and SecurityLogging
Summary
Appendix E. Resources and Mailing Lists
Relevant Websites
Mailing Lists and Newsgroups
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z

Using Public Keys in PHP

PHP includes support for the widely used and maintained OpenSSL library, which does nearly all the public key cryptography heavy lifting for you. You don't need to worry about how to generate public and private keys. In most cases you don't even need to worry about when to apply one over the other.

We'll start by looking at the easiest to use API for secure network communication and move on to encrypting and/or signing data for file storage or asynchronous data transfer.

SSL Streams

If you're already familiar with opening TCP/IP network streams and sending data to and/or reading data from a network socket, you're already halfway to applying encryption to that network data. Consider this simple HTTP client:

<?php
$conn = @fsockopen('tcp://www.example.com', 80);
If (!$conn) die('Unable to connect to www.example.com');
fwrite($conn, "GET / HTTP/1.0\r\n");
fwrite($conn, "Host: www.example.com\r\n\r\n");
fpassthru($conn);
?>

By doing nothing more than changing the first line to

$conn = @fsockopen('ssl://www.example.com', 443);

we instruct the PHP streams layer to generate a key pair, request www.example.com's public key, and transparently apply encryption/decryption to data sent over the stream. That's all it takes!

As of PHP5 we can also create ssl:// server sockets using this easy syntax:

<?php
$server = stream_socket_server('ssl://0.0.0.0:443');
while ($conn = stream_socket_accept($server)) {
  /* handle_http_request() is a made up function,
     try writing one of your own! */
  handle_http_request($conn);
  fclose($conn);
}
?>

The 0.0.0.0 value means "accept connections to any address associated with this server." Although we used port 443 for this example, we're not actually limited to accepting only HTTPs connections. We could listen for LDAPs connections on port 445 or make up our own application layer protocol and listen on whatever port we want to.

Generating a Public Key Certificate and Private Key

Apart from providing SSL extensions to transport-layer protocols, such as TCP, and application-layer protocols, such as HTTP and FTP, the OpenSSL extension also provides a rich API for generating public/private key pairs, preparing Certificate Signing Requests (CSRs), and even producing self-signed certificates.

The first step in using the OpenSSL extension is to create a public/private key pair. We'll do that by calling the openssl_pkey_new() function. When called without arguments, it will use defaults found in your systems openssl.conf file. You may, and possibly should, override these values by passing an array. A full list of options can be found in the online manual (http://www.php.net/openssl_csr_new); for now, we'll focus on the most common setting: private_key_bits.

$confargs = array('private_key_bits' => 2048);
$pkey = openssl_pkey_new($configargs);
openssl_pkey_export($pkey, 'private_key.pem');

Next, because OpenSSL expects that you'll be guarding against Man in the Middle attacks (described earlier), we'll need to generate a CSR. openssl_csr_new() expects the $pkey pair along with some identifying information that the key signer will use to confirm your identity.

$info = array(
    'countryName' => 'US',
    'stateOrProvinceName' => 'California',
    'localityName' => 'Placeopolis',
    'organizationName' => 'Thingy Industries',
    'organizationalUnitName' => 'Thingy R&D',
    'commonName' => 'Joe Josephson',
    'emailAddress' => 'joe@example.com');
$csr = openssl_csr_new($info, $pkey);
openssl_csr_export($csr, 'cert_request.csr');

countryName should always be the two letter ISO country code. emailAddress should conform to an RFC822 standard email address. The rest of the fields are essentially freeform, but should contain reasonable values that reflect reality.

Now that we have a certificate request in the form of a CSR file, we can send it off to our signing authority of choice. While we wait for their response, we can put our own signature on our public key. This has the effect of saying, "I certify that I am myself and you can trust me because I said so." Not the most resounding testimonial, but while we wait for a response, it will serve our purposes.

$cert = openssl_csr_sign($csr, NULL, $pkey, 365);
openssl_x509_export($cert, 'mycertificate.crt');

This will create a self-signed certificate that will expire one year in the future. Now that we have both a certificate and a private key, let's put it to use.

Encrypting/Decrypting Data

Because public and private keys need not be stored together, one potential use would be to keep the public key on a Web server where data is collected and encrypt it prior to storing it in a database. Then, even if our Web server and database server are compromised, the stolen data and passwords are useless because the attacker does not know our private key.

<?php
$pkey = 'file:///etc/public_keys/dbkey.crt';
openssl_public_encrypt($_POST['credit_card'], $cryptnum, $pkey);
$sql = sprintf("INSERT INTO billing (userid, ccnum) values(%d, '%s')",
                    $_SESSION['userid'], addslashes($cryptnum));
database_query($sql) or die('Unable to insert credit card data');
?>

When this script runs, any data posted from the form's credit_card field will be encrypted and added to the database for the user identified by the user ID stored in the currently active session. A third server, perhaps one that is inaccessible from the Internet and therefore not prone to intrusion, can then be responsible for retrieving the data and decrypting it with the matching private key.

The size of the database field needed to store the encrypted credit card number will vary depending on the keysize and the amount of data being encrypted. Assuming we're dealing with a 2,048 bit keysize, the size of an encryption block will be 256 bytes long (2,048 bits at 8 bits per byte).

Data must always be encoded in whole multiples of blocks, so even though a credit card number is typically only 16 bytes long, the data is treated as a whole block (256 bytes) and encrypted as such. Therefore, our database field must be at least char(256).

A more generic formula for determining the resulting size of encrypted data in bytes ($outsize), given an initial data size of $insize bytes for a keysize of $keysize bits, is

$outsize = ceil($insize/($keysize/8))*($keysize/8);

Encrypting and Sending Secure Emails Using S/MIME

Bob's trip to Maui on the company jet was really a corporate espionage mission. After infiltrating the Widget Works, he needs to report back his findings to P. H. Boss, but doesn't want to risk Wally, the Widget Works security guard, discovering that he knows their secrets. The best way for Bob to guard against this is to encrypt his message using P. H. Boss's public key.


<?php
$message_headers = array('To: phboss@thingy.example.com',
                         'From: bob@spy.example.com',
                         'Subject: Espionage Summary');
if (openssl_pkcs7_encrypt('espionage_summary.txt', 'espionage_summary.pkcs7',
 file_get_contents('phboss.crt'), $message_headers)) {
  mail('phboss@thingy.exmaple.com',
       'Espionage Summary',
       file_get_contents('espionage_summary.pkcs7'),
       $message_headers);
} else {
  die(openssl_error_string());
}
?>

When P. H. Boss receives Bob's email, he may need to send back additional instructions. It wouldn't do to have Wally or anyone else at Widget Works intercept those instructions, so he encrypts his response before sending it back. When Bob receives that response, he'll need to decrypt it:

<?php
$cert = file_get_contents('bob.crt');
$pkey = file_get_contents('bob.pem');
if (!openssl_pkcs7_decrypt('new_instructions.pkcs7',
                           'new_instructions.txt',
                           $cert, $pkey)) {
  die(openssl_error_string());
}
? >