Topic: [Mod] ColorCaptcha
In Practice: here
By Itself: here
EDIT:: please see here for the newer version.
I was tossing this idea around in my head for a while before I started using PunBB. The idea is simple: have the user differentiate between colors of characters. The user would only enter in the characters of a certain color to pass the captcha. It was meant to be easy for the user to understand but difficult for a bot to. The bot would try to enter in all of the letters, normally, and fail the test.
I'm not saying that it's 100% uncrackable, which I'm sure it isn't, but I think it is a nice idea. I have not seen this done anywhere before, but it might have been.
Here is the modified "image.php" code from the "pun_antispam" extension:
<?php
/**
* Generates a CAPTCHA picture
*
* @copyright Copyright (C) 2008 PunBB, partially based on code by Jamie Furness
* @license http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
* @package pun_antispam
* modified by James Anderson :)
*/
// Generate a random string
function pun_antispam_rand_str()
{
return strtr(substr(strtolower(md5(uniqid(rand(), 1))), 2, 6), 'abcdef', '165380');
}
// Output CAPTCHA string into an image
function pun_antispam_image($string)
{
$im = imagecreatetruecolor(100, 18);
// Make the background white
imagefilledrectangle($im, 0, 0, 99, 17, 0xFFFFFF);
$red = imagecolorallocate($im, 255, 0, 0);
$blue = imagecolorallocate($im, 0, 0, 255);
$noise = imagecolorallocate($im, 255, 0, 0);
$x = 0;
while($x <= 5) {
$usechars .= substr($string, mt_rand(0, strlen($string)-1), 1);
$color = rand(0,1); //is this character red or blue? make it up
$pallet = $pallet.$color; //This attaches a number, 0 or 1, to each character, determining whether it is red or blue
//pallet is an all numerical string. there are no letters in pallet
$x++;
}
$pallet{0} = rand(0,1); //if the first is red, the last has to be blue, and vice versa
if($pallet{0} == 1) { //this is to ensure that there will always be at least one red and at least one blue
$pallet{5} = 0;
}
else {
$pallet{5} = 1;
}
$px = rand(1,10); //moves it around a bit, x
//draw each character
//reads pallet to see whether the letter is red or blue
$j = 0;
while($j <= 5) {
if($pallet{$j} == 0) {
$y = rand(2,4);
imagestring($im, 5, $px, $y, $usechars{$j}, $red);
$list .= $usechars{$j}; //make the list of red chars
}
elseif($pallet{$j} == 1) {
$y = rand(2,4);
imagestring($im, 5, $px, $y, $usechars{$j}, $blue);
}
else { die("Something went wrong in pallet. It didn't make any colors."); }
$j++;
$px = $px + 15; //move for the next char
}
//make some noise
while($k<(100*18)/1000) { //where it says 1000, raise/lower the value to increase or decrease the noise leve. Higher numbers = LESS noise
imageline($im, mt_rand(0,100), mt_rand(0,18), mt_rand(0,100), mt_rand(0,18), $noise);
$k++;
}
sleep(1);
header('Content-type:image/gif');
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Pragma: no-cache');
imagegif($im, null, 30);
imagedestroy($im);
return $list; //the list of red chars
}
session_start();
$pun_antispam_string = pun_antispam_rand_str();
$_SESSION['pun_antispam_text'] = pun_antispam_image($pun_antispam_string);
?>
And I modified the English language file (pun_antispam.php) too, to make it more obvious to the user:
<?php
// Language definitions used in pun_antispam
$lang_pun_antispam = array(
'Captcha' => 'Captcha',
'Captcha Info' => 'Please enter <i>only</i> the <b><font color="red">red</font></b> characters in the image.',
'Invalid Text' => 'The captcha text you entered appears to be wrong. <b>Please <i>only</i> enter the <font color="red">red</font> characters.</b>',
'Captcha admin head' => 'Setup which actions are protected by a captcha',
'Captcha admin info' => 'You may enable captcha in certain areas of your forum if you are experiencing problems with spam.',
'Captcha admin legend' => 'Enable Captcha',
'Captcha registrations info' => 'Require a captcha before users may register. This can be helpful to stop spam.',
'Captcha login info' => 'Require a captcha when logging in. This can be helpful to stop brute-force attacks.',
'Captcha reset info' => 'Require a captcha to be entered when a user tries to reset their password.',
'Captcha guestpost info' => 'Require a captcha for guest posting (if enabled one).'
);
?>
Please feel free to make any further modifications if PunBB's license allows it. You can see this in practice here and the image by itself here.
I also thought about this usage with colorblind users. Although the colors might not look like how a non-colorblind user sees, they would still be able to tell the difference between red and blue. The colorblind would most likely know how they see red and how they see blue, and could still pass the captcha.
Please leave any questions or comments, you can use this in any way you'd like as long as it follows PunBB's license. I'm actually not familiar with the license myself, so if I wasn't even allowed to edit this extension then I apologize. Please also feel free to make any improvements you can think of.