How CAPTCHA Works? And a Simple Script in PHP

[For
this post I'm
presuming that you
are familiar with CAPTCHA, if not please read this style="font-style: italic;" href="http://en.wikipedia.org/wiki/Captcha"
target="_blank">Introduction
to CAPTCHA]


src="http://one.arvind.googlepages.com/generated_captcha.png"
alt="CAPTCHA Image Generated by Our Script"
title="CAPTCHA Image Generated by Our Script" height="53" width="150">Today
we are going to see
how CAPTCHA
(Completely Automated Public
Turing test to tell Computers
and Humans Apart) works and style="font-style: italic;"
href="http://computer.howstuffworks.com/captcha.htm" target="_blank">how
it minimizes automatic sign-up
of
formhref="http://computer.howstuffworks.com/captcha.htm" target="_blank">s.
We will also be creating a
simple CAPTCHA script in
PHP to illustrate this.


Basically CAPTCHA works in
the
following manner:




  1. Create Random Value:
    Some random string is generated, random values are often hard to guess
    and predict.




  2. Generate an Image:
    Images are used as these are generally a lot harder to read for
    computers while being nice and readable to humans. This is also the
    most important step as simple text in images can be read (and CAPTCHA
    cracked) quite easily. To make it difficult for them, developers employ
    different techniques so that the text in the image becomes hard to read
    for computers. Some create zig-zag lines for background while others
    twist-and-turn individual characters in the image. Possibilities are
    many and new techniques are being developed all the time as crackers
    are always into finding ways to break them.




  3. Store it: The random
    string generated (which is also in the image) is stored for matching
    the user input. The easiest way to do so is to use the style="font-style: italic;" href="http://in.php.net/session"
    target="_blank">Session
    variables.




  4. Matching: After the
    above step, the CAPTCHA image is generated and shown on some form which
    we want to protect from being abused. The users fills in the form along
    with the CAPTCHA text and submits it. Now we have the following:




    1. All submitted form
      data.




    2. CAPTCHA string
      (from form), input by user.




    3. CAPTCHA string
      (real one, generated by us), from session variable. Session variable is
      generally used as it can keep stored values across page requests. Here,
      we needed to preserve stored values from one page (form page) to
      another (action page-that receives form data).






  5. If both match, it's
    okay otherwise not, in that case we can give the user a message that
    the CAPTCHA they had entered was wrong and their form could not be
    submitted. You could also ask them to verify it again.




The following image might
illustrates
this better:


src="http://one.arvind.googlepages.com/captch_generation_and_matching_STEPS.png"
alt="CAPTCHA Generation and Matching" align="middle" height="636"
width="417">

How CAPTCHA is Generated and Matched


From the above image it's
quite clear
that when someone requests the form page, the CAPTCHA text is
generated and sent back to requesting user, but only in the form of
an image. If the requester is a human he'd not have much difficulty
reading the image and inputting the text when asked but if it's a
bot it might face difficulties guessing whats in the image. In the
next step when we match the string generated and the one the user had
input, we can restrict automated form submissions.


The following is the code that does this, it'll just output
the CAPTCHA image to the browser when the script is requested:


style="color: rgb(0, 0, 187);"><?php
style="color: rgb(255, 128, 0);">/********************************************************
 * File:        captcha.php                             *
 * Author:      Arvind Gupta (www.arvindgupta.co.in)    *
 * Date:        12-Mar-2009                             *
 * Description: This file can be embedded as image      *
 *              to show CAPTCHA/                        *
 ********************************************************/

// The number of characters you
// want your CAPTCHA text to have
style="color: rgb(0, 0, 187);">definestyle="color: rgb(0, 119, 0);">(style="color: rgb(221, 0, 0);">'CAPTCHA_STRENGTH'style="color: rgb(0, 119, 0);">,style="color: rgb(0, 0, 187);"> 5style="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">/****************************
 *        INITIALISE        *
 ****************************/
// Tell PHP we're going to use
// Session vars
style="color: rgb(0, 0, 187);">session_startstyle="color: rgb(0, 119, 0);">();

style="color: rgb(255, 128, 0);">// Md5 to generate the random string
style="color: rgb(0, 0, 187);">$random_str style="color: rgb(0, 119, 0);">= style="color: rgb(0, 0, 187);">md5style="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">microtimestyle="color: rgb(0, 119, 0);">());

style="color: rgb(255, 128, 0);">// Trim required number of characters
style="color: rgb(0, 0, 187);">$captcha_str style="color: rgb(0, 119, 0);">= style="color: rgb(0, 0, 187);">substrstyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$random_strstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">CAPTCHA_STRENGTHstyle="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Allocate new image
style="color: rgb(0, 0, 187);">$width style="color: rgb(0, 119, 0);">= (style="color: rgb(0, 0, 187);">CAPTCHA_STRENGTHstyle="color: rgb(0, 119, 0);"> * style="color: rgb(0, 0, 187);">10style="color: rgb(0, 119, 0);">)+style="color: rgb(0, 0, 187);">10style="color: rgb(0, 119, 0);">;
style="color: rgb(0, 0, 187);">$height style="color: rgb(0, 119, 0);">= style="color: rgb(0, 0, 187);">20style="color: rgb(0, 119, 0);">;

style="color: rgb(0, 0, 187);">$captcha_img style="color: rgb(0, 119, 0);">=style="color: rgb(0, 0, 187);">ImageCreatestyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$widthstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$heightstyle="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// ALLOCATE COLORS
// Background color-black
style="color: rgb(0, 0, 187);">$back_color style="color: rgb(0, 119, 0);">= style="color: rgb(0, 0, 187);">ImageColorAllocatestyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Text color-white
style="color: rgb(0, 0, 187);">$text_color style="color: rgb(0, 119, 0);">= style="color: rgb(0, 0, 187);">ImageColorAllocatestyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">255style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">255style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">255style="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Line color-red
style="color: rgb(0, 0, 187);">$line_color style="color: rgb(0, 119, 0);">= style="color: rgb(0, 0, 187);">ImageColorAllocatestyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">255style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">/****************************
 *     DRAW BACKGROUND &    *
 *           LINES          *
 ****************************/
// Fill background color
style="color: rgb(0, 0, 187);">ImageFillstyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$back_colorstyle="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Draw lines accross the x-axis
style="color: rgb(0, 119, 0);">for(style="color: rgb(0, 0, 187);">$i style="color: rgb(0, 119, 0);">=style="color: rgb(0, 0, 187);"> 0style="color: rgb(0, 119, 0);">; style="color: rgb(0, 0, 187);">$i style="color: rgb(0, 119, 0);"><
style="color: rgb(0, 0, 0);">$widthstyle="color: rgb(0, 0, 0);">style="color: rgb(0, 119, 0);">;style="color: rgb(0, 0, 187);"> $istyle="color: rgb(0, 119, 0);"> +=style="color: rgb(0, 0, 187);"> 5style="color: rgb(0, 119, 0);">)
    style="color: rgb(0, 0, 187);">ImageLinestyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$istyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$istyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">20style="color: rgb(0, 119, 0);">,style="color: rgb(0, 0, 187);"> $line_colorstyle="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Draw lines accross the y-axis
style="color: rgb(0, 119, 0);">for(style="color: rgb(0, 0, 187);">$i style="color: rgb(0, 119, 0);">= style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">; style="color: rgb(0, 0, 187);">$istyle="color: rgb(0, 119, 0);"> < style="color: rgb(0, 0, 187);">20style="color: rgb(0, 119, 0);">;style="color: rgb(0, 0, 187);"> $istyle="color: rgb(0, 119, 0);"> += style="color: rgb(0, 0, 187);">5style="color: rgb(0, 119, 0);">)
    style="color: rgb(0, 0, 187);">ImageLinestyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">0style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$istyle="color: rgb(0, 119, 0);">,
style="color: rgb(0, 0, 0);">$widthstyle="color: rgb(0, 0, 0);">style="color: rgb(0, 0, 187);">style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$i style="color: rgb(0, 119, 0);">,style="color: rgb(0, 0, 187);"> $line_colorstyle="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">/****************************
 *      DRAW AND OUTPUT     *
 *          IMAGE           *
 ****************************/
// Draw the random string
style="color: rgb(0, 0, 187);">ImageStringstyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">5style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">5style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">2style="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$captcha_strstyle="color: rgb(0, 119, 0);">, style="color: rgb(0, 0, 187);">$text_colorstyle="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Carry the data (KEY) through session
style="color: rgb(0, 0, 187);">$_SESSIONstyle="color: rgb(0, 119, 0);">[style="color: rgb(221, 0, 0);">'key'style="color: rgb(0, 119, 0);">] = style="color: rgb(0, 0, 187);">$captcha_strstyle="color: rgb(0, 119, 0);">;

style="color: rgb(255, 128, 0);">// Send data type
style="color: rgb(0, 0, 187);">headerstyle="color: rgb(0, 119, 0);">(style="color: rgb(221, 0, 0);">"Content-type: image/jpeg"style="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Output image to browser
style="color: rgb(0, 0, 187);">ImageJPEGstyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">);

style="color: rgb(255, 128, 0);">// Free-Up resources
style="color: rgb(0, 0, 187);">ImageDestroystyle="color: rgb(0, 119, 0);">(style="color: rgb(0, 0, 187);">$captcha_imgstyle="color: rgb(0, 119, 0);">);
style="color: rgb(0, 0, 187);">?>

Okay, this it for this, in
the next one
we'll integrate this CAPTCHA script into one form and see how it
works. Till then goodbye!

Check out this stream