5,543,170 members and growing! (190 online)
Email Password   helpLost your password?
Web Development » Web Security » Security     Beginner License: The Code Project Open License (CPOL)

Captcha Image in PHP

By Mohammad Dayyan

Generate images for CAPTCHA validation
PHP, Apache, Dev

Posted: 2 Jun 2008
Updated: 17 Sep 2008
Views: 5,022
Bookmarked: 3 times
Announcements



Search    
Advanced Search
Sitemap
13 votes for this Article.
Popularity: 5.22 Rating: 4.69 out of 5
0 votes, 0.0%
1
1 vote, 7.7%
2
0 votes, 0.0%
3
2 votes, 15.4%
4
10 votes, 76.9%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article
windows_server.jpg

linux_server.jpg

Introduction

You can use this class to increase your web's form security and perevent auotomatic registration.

Using the code

First we need to write a class to generates random characters
DayyanRandomCharacters Class generates random character :

class DayyanRandomCharacters
{
    private $id;
    private $key_str;
    private $Code;//Orginal string code

////////////////////////////////////////////////////////////////////////////////

    public function __construct()
    {
        $this -> create();
    }

////////////////////////////////////////////////////////////////////////////////

    public function get_code()
    {
        return $this -> Code;
    }

////////////////////////////////////////////////////////////////////////////////

    private function create()
    {
        $string = "";
        $string = md5(rand(0, microtime() * 1000000));
        $this-> id = $this-gtCode   = substr($string, 3, 6);
        $this-> key_str = md5(rand(0, 999));
    }

////////////////////////////////////////////////////////////////////////////////

    private function get_rnd_iv($iv_len)
    {
        $iv = '';
        while ($iv_len-- > 0) {
            $iv .= chr(mt_rand() 0xff);
        }
        return $iv;
    }

////////////////////////////////////////////////////////////////////////////////

    public function get_id()
    {

        return urlencode($this -> md5_encrypt($this-gtid, $this-gtkey_str));
    }

////////////////////////////////////////////////////////////////////////////////

    public function get_key()
    {
        return $this -> key_str;
    }

////////////////////////////////////////////////////////////////////////////////
    //encrypt id 
    private function md5_encrypt($plain_text, $password, $iv_len = 16)
    {
        $plain_text .= "x13";
        $n = strlen($plain_text);
        if ($n % 16) $plain_text .= str_repeat("0", 16 - ($n % 16));
        $i = 0;
        $enc_text = $this -> get_rnd_iv($iv_len);
        $iv = substr($password ^ $enc_text, 0, 512);
        while ($i < $n)
        {
            $block = substr($plain_text, $i, 16) ^ pack('H*', md5($iv));
            $enc_text .= $block;
            $iv = substr($block . $iv, 0, 512) ^ $password;
            $i += 16;
        }
        return base64_encode($enc_text);
    }

////////////////////////////////////////////////////////////////////////////////

    public function md5_decrypt($enc_text, $password, $iv_len = 16)
    {
        $enc_text = base64_decode($enc_text);
        $n = strlen($enc_text);
        $i = $iv_len;
        $plain_text = '';
        $iv = substr($password ^ substr($enc_text, 0, $iv_len), 0, 512);
        while ($i < $n)
        {
            $block = substr($enc_text, $i, 16);
            $plain_text .= $block ^ pack('H*', md5($iv));
            $iv = substr($block . $iv, 0, 512) ^ $password;
            $i += 16;
        }
        return preg_replace('/\\x13\\x00*$/', '', $plain_text);
    }
}

 

OK, now we can get encrypted id and key with this code :
    $DayyanRandomCharacters = new DayyanRandomCharacters();
    $id = $DayyanRandomCharacters -> get_id();
    $key = $DayyanRandomCharacters -> get_key();
    $Code = $DayyanRandomCharacters -> get_code();//Orginal String code

Now we have to write a class to generates CAPTCHA image : DayyanConfirmImageClass.php
This class can use above random characters to generate CAPTCHA image.



DayyanConfirmImageClass.php's fields :

    private $showLine; // whether show line for windows image
    private $Characters; // random characters
    //colors' code to fill background
    private $Colors =  array (    '0' => '145',
                                '1' => '204',
                                '2' => '177',
                                '3' => '184',
                                '4' => '199',
                                '5' => '255');
                                
DayyanConfirmImageClass.php's methods :

__construct : Constructor of class
    public function __construct($ConfirmCode)
    {
        //Show lines in output image
        $this -> showLine = true; 
        
        //this class generates image with this characters
        $this -> Characters = $ConfirmCode; 
    }


ShowLine : Assigned $this -> showLine with $value
    public function ShowLine($value=false)
    {
        $this -> showLine = $value;
    }


ShowImage : Detected server operation and called $this -> win(); or $this -> linux();
because we don't have font like "tahomabd" in linux I used this function
    public function ShowImage()
    {
        //detect server operation system
        if ( strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' )    //windows detected
            $this -> win();
        else    //linux detected
            $this -> linux();
    }


win : Generate CAPTCHA image for windows
    private function win()
    {
        ////////////////////////////////////
        //background image
        $image = imagecreatetruecolor(320, 50) or 
            die("<b>". __FILE__ . "</b><br />" . __LINE__ . " : " 
                ."Cannot Initialize new GD image stream");
        $bg = imagecolorallocate($image, 255, 255, 255);
        imagefill($image, 10, 10, $bg);

        //generate black and white background
        for ($x=0; $x < 320; $x++)
        {
            for ($y=0; $y < 50; $y++)
            {
                $random = mt_rand(0 , 5);
                $temp_color = imagecolorallocate($image, $this -> 
                Colors["$random"], $this -> Colors["$random"], 
                $this -> Colors["$random"]);
                imagesetpixel( $image, $x, $y , $temp_color );
            }
        }

        //Characters color
        $char_color = imagecolorallocatealpha($image, 0, 0, 0, 90);

        //Font
        $font = "tahomabd";

        ////////////////////////////////////
        //Draw characters

        $char = "";

        $char = $this -> Characters[0];
        $random_x = mt_rand(10 , 20);
        $random_y = mt_rand(35 , 45);
        $random_angle = mt_rand(-20 , 20);
        imagettftext($image, 30, $random_angle, $random_x, 
            $random_y, $char_color, $font, $char);



        $char = $this -> Characters[1];
        $random_x = mt_rand(50 , 70);
        $random_y = mt_rand(35 , 45);
        $random_angle = mt_rand(-20 , 20);
        imagettftext($image, 30, $random_angle, $random_x, 
            $random_y, $char_color, $font, $char);



        $char = $this -> Characters[2];
        $random_x = mt_rand(100 , 120);
        $random_y = mt_rand(35 , 45);
        $random_angle = mt_rand(-20 , 20);
        imagettftext($image, 30, $random_angle, $random_x, 
            $random_y, $char_color, $font, $char);


        $char = $this -> Characters[3];
        $random_x = mt_rand(150 , 170);
        $random_y = mt_rand(35 , 45);
        $random_angle = mt_rand(-20 , 20);
        imagettftext($image, 30, $random_angle, $random_x, 
            $random_y, $char_color, $font, $char);


        $char = $this -> Characters[4];
        $random_x = mt_rand(200 , 220);
        $random_y = mt_rand(35 , 45);
        $random_angle = mt_rand(-20 , 20);
        imagettftext($image, 30, $random_angle, $random_x, 
            $random_y, $char_color, $font, $char);


        $char = $this -> Characters[5];
        $random_x = mt_rand(250 , 270);
        $random_y = mt_rand(35 , 45);
        $random_angle = mt_rand(-20 , 20);
        imagettftext($image, 30, $random_angle, $random_x, 
            $random_y, $char_color, $font, $char);

        ////////////////////////////////////
        //Image lines
        if ($this -> showLine)
        {
            for ($i=0; $i<320; $i++ )
            {
                if ($i%10 == 0)
                {
                    imageline ( $image, $i, 0, $i+10, 50, $char_color );
                    imageline ( $image, $i, 0, $i-10, 50, $char_color );
                }
            }
        }

        ////////////////////////////////////
        return imagepng($image); //return image
        imagedestroy($image); //frees any memory associated with $image
    }


linux : Generate CAPTCHA image for linux like above function
    private function linux()
    {
        ////////////////////////////////////
        //Background image
        $image = imagecreatetruecolor(150, 50) or 
            die("<b>" . __FILE__ . "</b><br />" . __LINE__ . " : " 
                ."Cannot Initialize new GD image stream");
        $bg = imagecolorallocate($image, 255, 255, 255);
        imagefill($image, 10, 10, $bg);

        //generate black and white background
        for ($x=0; $x < 150; $x++)
        {
            for ($y=0; $y < 50; $y++)
            {
                $random = mt_rand(0 , 5);
                $temp_color = 
                imagecolorallocate($image, $this -> Colors["$random"], 
                $this -> Colors["$random"], $this -> Colors["$random"]);
                imagesetpixel( $image, $x, $y , $temp_color );
            }
        }
        
        //Characters color
        $char_color = imagecolorallocatealpha($image, 0, 0, 0, 60);

        ////////////////////////////////////
        //Image Info
        $font = 5;

        ////////////////////////////////////
        //Draw characters

        $char = $this -> Characters[0];
        $random_x = mt_rand(10 , 20);
        $random_y = mt_rand(15,25);
        imagestring($image, $font, $random_x, 
            $random_y, $char, $char_color);



        $char = $this -> Characters[1];
        $random_x = mt_rand(30 , 40);
        $random_y = mt_rand(15,25);
        imagestring($image, $font, $random_x, 
            $random_y, $char, $char_color);



        $char = $this -> Characters[2];
        $random_x = mt_rand(50 , 60);
        $random_y = mt_rand(15,25);
        imagestring($image, $font, $random_x, 
            $random_y, $char, $char_color);


        $char = $this -> Characters[3];
        $random_x = mt_rand(70 , 80);
        $random_y = mt_rand(15,25);
        imagestring($image, $font, $random_x, 
            $random_y, $char, $char_color);


        $char = $this -> Characters[4];
        $random_x = mt_rand(90 , 100);
        $random_y = mt_rand(15,25);
        imagestring($image, $font, $random_x, 
            $random_y, $char, $char_color);


        $char = $this -> Characters[5];
        $random_x = mt_rand(110 , 120);
        $random_y = mt_rand(15,25);
        imagestring($image, $font, $random_x, 
            $random_y, $char, $char_color);

        ///////////////////////
        return imagepng($image); //return image
        imagedestroy($image); //frees any memory associated with $image
    }



Now we have to use above classes :
include/index.php : Generates and return image with $_REQUEST['id'] and $_REQUEST['key']
try
{
    include_once("DayyanConfirmImageClass.php");
    include_once("DayyanRandomCharactersClass.php");

    $id = (isset($_REQUEST['id'])  !empty($_REQUEST['id'])) 
            ? trim($_REQUEST['id']) : exit;
    $key = (isset($_REQUEST['key'])  !empty($_REQUEST['key'])) 
            ? trim($_REQUEST['key']) : exit;

    $DayyanRandomCharacters = new DayyanRandomCharacters();
            //encrypt string
    $ConfirmString = 
        strtoupper($DayyanRandomCharacters -> md5_decrypt($id, $key));

    $DayyanConfirmImage = new DayyanConfirmImage($ConfirmString);
    $DayyanConfirmImage -> ShowLine(false);
    $DayyanConfirmImage -> ShowImage();
}
catch(Exception $ex)
{
    echo 'Caught exception: ',  $e -> getMessage(), '\n';
    exit;
}



index.php : Generates random characters and send $_REQUEST['id'] and $_REQUEST['key'] for generete image.
include_once("include/DayyanRandomCharactersClass.php");

try
{
    $DayyanRandomCharacters = new DayyanRandomCharacters();
    $id = $DayyanRandomCharacters -> get_id();
    $key = $DayyanRandomCharacters -> get_key();
    $Code = $DayyanRandomCharacters -> get_code();
}
catch(Exception $ex)
{
    echo 'Caught exception: ',  $e -> getMessage(), "<br />";
    exit;
}

Now with IMG tag we can see result :
<img src="include/?id=<?php echo $id;?>
    key=<?php echo $key; ?>" 
    alt="Dayyan Confirm Image" title="Dayyan Confirm Image" 
    name="DayyanConfirmImage" border="0" id="DayyanConfirmImage" />



<input name="Code" type="text" id="Code" value="<?php echo $Code ?>" />

Enjoy !



History


Friday, June 13, 2008 : Fixed bug ( reported by signuperror )

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mohammad Dayyan



Location: Iran, Islamic Republic Of Iran, Islamic Republic Of

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 7 of 7 (Total in Forum: 7) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralVery usefulmemberPerspx14:46 6 Aug '08  
GeneralRe: Very usefulmemberMohammad Dayyan15:24 6 Aug '08  
Generalbut... [modified]membersignuperror4:20 12 Jun '08  
GeneralRe: but...memberM-Dayyan11:10 12 Jun '08  
GeneralRe: but... [modified]memberM-Dayyan14:25 12 Jun '08  
GeneralThanks DayyanmemberHari Om Prakash Sharma1:30 6 Jun '08  
GeneralRe: Thanks DayyanmemberM-Dayyan2:22 6 Jun '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 17 Sep 2008
Editor:
Copyright 2008 by Mohammad Dayyan
Everything else Copyright © CodeProject, 1999-2008
Mail5 | Advertise on the Code Project