Home > Code Snippets, PHP, Tips > A Mathematical Captcha – Reinventing the Wheel

A Mathematical Captcha – Reinventing the Wheel

April 19th, 2010 Leave a comment Go to comments

For a long time I have been using the image captcha with random characters, and got fed up. I had seen numeric computational captcha or Mathematical captcha where one has to calculate the answer of an equation with simple arithmetic and supply the result for verification. Last night I was pondering over this while watching a movie on the TV. Well the out come is obvious.

A Mathematical Captcha class in php, was the result. I wanted it to work in a particular way, and not to disturb certain settings avoided the use of sessions. Rather used cookie to set the encrypted result of the evaluated captcha. For making the class a bit generic such that we could use in other sites, just made the numbers, methods and complexity a property.

The class defines its properties for a minimum, since for my requirement this was enough. And the setters are provided for adaptablity to different capatcha behaviour across the same project. Though I do agree that the image size and font selection should be made dynamic for making the captcha true object capable. Which I was not so interested at the time.

    private $numbers;
    private 
$methods;
    private 
$complexity;
    
    function 
__construct(){
       
$this->set_numbers();
       
$this->set_methods();
       
$this->set_complexity();
    }
    
    function 
set_numbers($n = array()){
      if(empty(
$n))
        
$n = array(123456789);
      
$this->numbers $n;
    }
    
    function 
set_methods($m = array()){
      if(empty(
$m))
        
$m = array('+','-');
      
$this->methods $m;
    }
    
    function 
set_complexity($c 4){
       
$this->complexity $c;
    }

The generatemc function generates the captcha code with random numbers and random operators concatenated into a string.

   private function generatemc(){
        
$str '';
        for(
$j 0$j $this->complexity$j++){
            if(
$j 0){
               
$n array_rand($this->methods);
               
$str .= ' '.$this->methods[$n].' ';
            }
            
$n array_rand($this->numbers);
            
$str .= $this->numbers[$n];
        }
        return 
$str;
    }

This is where we evaluate the value of the equation, and set it as a cookie after oneway encrypting. Since this is the defacto method for password comparison in *nix (AFAIK) I thought that the level of security for this captcha better be limited at this level. Also the session would have been better, but I just wanted to deviate from the age old methods there. Hence used the cookie.

    
    private function 
setVal($mc){
        eval(
"\$val = $mc;");
        
setcookie("MathCaptcha"crypt($val));
    }

The public function which shows the captcha using gd functions. The width, height and font was defined only on trial and error, so I did not work for a dynamic method. I may work for the same in the future but the current scope does not need the same.

    public function captcha(){
        
$mc $this->generatemc();
        
$this->setVal($mc);
        
header("Content-type: image/gif");
        
$im = @imagecreate(14016) or die("Cannot Initialize new GD image stream");
        
$background_color imagecolorallocate($im255255255);
        
$text_color imagecolorallocate($im000);
        
imagestring($im500,  $mc .' = '$text_color);    
        
imagegif($im);
        
imagedestroy($im);
    }

Yes the checking code is a static function, and it also deletes the cookie after checking. Will need to write an ajax handler too which will be the next milestone for the same.

    public static function check($val){
        if(!isset(
$_COOKIE['MathCaptcha']))
            return 
false;
        
$crypted $_COOKIE['MathCaptcha'];    
        
setcookie("MathCaptcha"false);
        return 
crypt($val$crypted) == $crypted;
    }

Okay to use this, you will need a captcha delivery file, which has the following code, and the form should contain an image tag pointing to the delivery file as in the listing below this.

$cc = new MathCaptcha();
    
$cc->captcha();

<img src="delivery.php" />

Test is done using static invokation of method check method,

MathCaptcha::check($code)

If this is of interest to some one, the full code for download is added to the downloads. Mathematical Captcha (804)

Mathematical Captcha, Computational Captcha, php captcha

Categories: Code Snippets, PHP, Tips Tags: ,
  1. August 11th, 2010 at 09:31 | #1

    Hey, this is great. Was just thinking about it the other day. I wonder what made you go with storing the captcha in the cookie rather than in a session?

  2. September 7th, 2010 at 22:10 | #2

    Storing the captcha in the cookie ? Just a trivial joke, I just wanted to deviate from the age old methods there. Hence used the cookie.

  1. No trackbacks yet.

two + seven =