Click here to Skip to main content
Email Password   helpLost your password?
Screenshot - captcha.jpg

Introduction

One day I've decided to build own CAPTCHA for my project. Why? First of all I need quite strong bot protection. Second reason � I want to make my contribution for the community. That's why I decided to make this project completely free for use.

Why I'm thinking that result of my work is a real strong protection? First of all it's new � so there are no ready OCR's for this one. Also, you can change it by yourself � and receive completely different CAPTCHA. I'm calling my CAPTCHA "ADSS AntiBot". I've a friend, he breaking such security using OCR. He said � not very bad.

You can make your own protection based on this (link to us greatly appreciated, ADSS).

Background

Everybody knows that world wide web filled up with spam bots. And webmaster (usually using developers) fight against this problem. Because every webmaster dreams about real visitors, not about thousands of bots that using some service and even resell it on another web site. So, the things known as CAPTCHA ("Completely Automated Public Turing test to tell Computers and Humans Apart") were made to fight against bots. I'm using term AntiBot for my application.


Using the code

How to use downloaded source? Very easy. Just put some image on your asp.net page with ImageURL set to captcha.ashx. This handler generates new image each time it accessed, and stores right value into the session.

string number_server_side = (string)Session[ADSSAntiBot.SESSION_CAPTCHA];
if (number_server_side == TextBox_number.Text)
            {
// The code entered is valid

            }
            else
            {
// The code entered invalid

            }

This way you can use created HTTP handler.

Another thing, I want to note, the image size. You can easily set it using ADSSAntiBot public constructor inside ProcessRequest function of handler.

     public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "image/jpeg";
        ADSSAntiBot captcha = new ADSSAntiBot(300,80); // Set size using constructor

        string str = captcha.DrawNumbers(5);
        if (context.Session[ ADSSAntiBot.SESSION_CAPTCHA] == null) context.Session.Add(ADSSAntiBot.SESSION_CAPTCHA, str);
        else
        {
            context.Session[ ADSSAntiBot.SESSION_CAPTCHA] = str;
        }
        Bitmap bmp = captcha.Result;
        bmp.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
    }
 

Next picture shows result of this code. Sometimes you want large image, sometimes smaller.


Screenshot - large_captcha.jpg

Points of Interest

So, how we are creating this "hard to OCR" image? And how to improve it?

We are using GraphicsPath to warp image. Basically transformations is sin wave, regular random noise and some rotation. What is the goal? To create text that can be read by the human, not by the bot. How we are making this? We are "shaking" subpaths of our text.

So, what is the goal of transform? First of all, we need to change it to make a letter separation hard. For this we are adding line through all the number displayed. Second thing, we need to remember, our numbers should be hard to OCR using a neural network. By moving path points randomly and by sin wave we are making line very think in some places. On the sample image, you can see this effect on "9" and "6".

The following function is the heart of our transformation:

    public GraphicsPath RandomWarp(GraphicsPath path)
    {
        // Add line //

        int PsCount = 10;
        PointF[] curvePs = new PointF[PsCount * 2];
        for (int u = 0; u < PsCount; u++)
        {
            curvePs[u].X = u * (Width / PsCount);
            curvePs[u].Y = Height / 2;
        }
        for (int u = PsCount; u < (PsCount * 2); u++)
        {
            curvePs[u].X = (u - PsCount) * (Width / PsCount);
            curvePs[u].Y = Height / 2 + 2;
        }
        path.AddLines(curvePs);
       
        double eps = Height * 0.05;
        double amp = rnd.NextDouble() * (double)(Height / 3);
        double size = rnd.NextDouble() * (double)(Width / 4) + Width / 8;
        double offset = (double)(Height / 3);

        PointF[] pn = new PointF[path.PointCount];
        byte[] pt = new byte[path.PointCount];

        GraphicsPath np2 = new GraphicsPath();

        GraphicsPathIterator iter = new GraphicsPathIterator(path);
        for (int i = 0; i < iter.SubpathCount; i++)
        {
            GraphicsPath sp = new GraphicsPath();
            bool closed;
            iter.NextSubpath(sp, out closed);

            Matrix m = new Matrix();
            m.RotateAt(Convert.ToSingle(rnd.NextDouble() * 30 - 15), sp.PathPoints[0]);
            m.Translate(-1 * i, 0);
            sp.Transform(m);
            np2.AddPath(sp, true);
        }
        for (int i = 0; i < np2.PointCount; i++)
        {
            pn[i] = Wave(np2.PathPoints[i], amp, size);
            pt[i] = np2.PathTypes[i];
        }
        GraphicsPath newpath = new GraphicsPath(pn, pt);
        return newpath;
    }  

We are not using lot of fonts like others do, not using colors. Color model only helps OCRing many captchas, font is not an obstacle too. But here we are making "random" font using this warp. I just wanted to show that .net framework makes it possible to protect site from Bots much better then other web languages. Also, I'm interesting in your suggestions about non-captcha bot protections. I'm going to continue my research in this direction.

History

The code described in this article is complete freeware. You can try it online.

Also, you can download the last version on ADSS Web Site.

Feel free to create your CAPTCHAs based on this one to fight against spam.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralVery Very Nice
blagoja
22:44 30 Jul '09  
Thanks for the code and teaching how to do it in future.
Very nice code i used in my web app.
Thanks Dmitry Salko and have a nice day Smile
GeneralI used in my project and convert it into vb Thanks for your code
jefferycxl
17:56 20 Jan '09  
Tried to use the code in asp.net (framework 1.0).
But I cannot use ashx file, so I saved the output image on the server then display it in the image holder.

Jefferycxl

GeneralHelp please!
Patrik Svitek
12:26 11 Mar '08  
hey thats pretty nice
i was wondering, since you said you have a friend that make's OCR's, if you could ask him to contact me because i need some help making an OCR
thanks alot

(my email is patrik_svitek7@hotmail.com)
GeneralCaptcha not working with UpdatePanel
Member 3236103
0:15 11 Feb '08  
hi..
nice code but there is one problem cpatcha image is not refresh when i do partial postback....
GeneralRe: Captcha not working with UpdatePanel
macload
10:24 14 Dec '09  
http://forums.asp.net/t/1210646.aspx[^]
GeneralBrowser incompatibility?
nemopeti
10:02 15 Oct '07  
First of all: Nice work Wink

In the test page I can't see the image on Firefox (Ie works fine).

In Firefox I see THIS
In the soure i see the img tag, but not the image.
GeneralRe: Browser incompatibility?
Dmitry Salko
10:09 15 Oct '07  
Thanks.
Very strange... I've tested it in Firefox 2, IE 6 and 7, Opera and Safari. This is my standard web testing package Smile

Possible you've images turned off in Firefox.
I'm sorry, but we are not using anything but IMG.

General4 out of 5 Bad
crb9000
5:49 9 Oct '07  
Looking at the sample site, 4 out of the 5 refreshes generated captchas that weren't even human readable. The real problem is betweeen 3's, 8's, and 9's. There has to be a balance. This one would cause my users, in a highly unionized, complaint file happy, government environment to totally rebel.

When its broke, trust government to find a better way to break it further.
GeneralRe: 4 out of 5 Bad
Dmitry Salko
6:23 9 Oct '07  
Hi, you are too lucky. Ok, I'll work on more readable captcha in future. I'm thinking about some 3D or so.
GeneralNice code, but nothing new
Sire404
5:44 9 Oct '07  
The code is nice, but unfortunately it brings nothing new. OCR algorithms could easily be modified to have a really high success rate for beating this.

So far, the only successful bot protection I know of is Bayesian filtering. Check out Akismet (http://akismet.com/) or build your own (search for Bayesian on this site for example).




--------------------
No one is perfect.
Welll, there was this guy... but we killed him.

GeneralRe: Nice code, but nothing new
Dmitry Salko
6:01 9 Oct '07  
Checked out the Akismet. Please let me know how this help me to protect registration process (for example for free email account) ?

Thanks.
GeneralRe: Nice code, but nothing new
Sire404
6:09 9 Oct '07  
It can't, and I haven't found any other solution that work well either.

But successfully registering to a free email service isn't the goal, sending spam is - and it will stop that very efficiently.


--------------------
No one is perfect.
Welll, there was this guy... but we killed him.

QuestionWhat about vision impaired surfers?
Bcouch
2:51 9 Oct '07  
I didn't see any provision for vision impaired surfers, such as an audio version.
AnswerRe: What about vision impaired surfers?
Dmitry Salko
4:36 9 Oct '07  
Hi, yes this is quite right question, and right now I'm working on it.
If you want to provide some help, please let me know.
GeneralVery Nice
merlin981
5:31 8 Oct '07  
Very nice and easy to implement. 5 from me


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I get my developer tools from Merlin A.I. Soft
Rhabot - World of Warcraft Bot
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

GeneralRe: Very Nice
Dmitry Salko
5:37 8 Oct '07  
Thanks. Smile
GeneralNice
Ben Daniel
13:51 7 Oct '07  
Neato. Can I just say, I realise it's not the point of your article but, I'd be interested in a further explanation on how the warp code actually works, specifically more detail on the GraphicsPath, GraphicsPathIterator & matrix bits. Confused



Thanks,
Ben Smile

GeneralRe: Nice
Dmitry Salko
23:14 7 Oct '07  
Thanks, Ben.
I'll try to update article with some explanations on GraphicsPath and other stuff soon.
GeneralRe: Nice
Ben Daniel
21:42 15 Oct '07  
Hi Dmitry, I see you've updated your article but I must confess that after rereading it, I'm still clueless about what a graphics path/sub path is and how it works.

Thanks,
Ben Smile


Last Updated 15 Oct 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010