Hi All,
I recently received a review about MyCaptcha control in CodePlex that proposed a couple of improvements in the source code. This review indicates that :
- Thread.Sleep is not a good way to ensure that unique characters are selected for teh Captcha text.
- Sending the Captcha text to rendering component (.ashx file) is insecure.
Based on the above objections, I modified the source code and re-uploaded it to Codeplex. The modifications are as follows:
First, I removed Thread.Sleep thing from MyCaptcha.ascx.cs and replaced it with a do {..} while (…) loop to ensure that no letter is duplicate:
char newChar = (char)0;
do
{
newChar = Char.ToUpper(Valichars[new Random(DateTime.Now.Millisecond).Next(Valichars.Count() - 1)]);
}
while (Captcha.Contains(newChar));
Captcha += newChar;
To improve security when passing the Captcha text to rendering component (GetImgText.ashx) to ways come to my mind:
- To include text generation logic into .ashx file
- To encrypt captcha text before passing it to .ashx file.
As I mentioned before, generating a random text should not be depended on the way we display it. Therefore I don’t like mingling up the two codes. So I added some code to use a Symmetric algorithm to encrypt/decrypt Captcha text.
Thus, I added a new static class called SecurityHelper which includes two encryption and decryption methods . Symmetric algorithms require a 16-letter key. Therefore I added a private property to give back the key. This key is optional and you can change it to whatever you would like:
private static byte[] SymmetricKey
{
get
{
return Encoding.UTF8.GetBytes(“1B2c3D4e5F6g7H81″);
}
}
This post is too short to include the body of EncryptString and DecryptString methods. You can download the source code and see to it.
Back to MyCaptcha.ascx.cs , we need to use SecurityHelper.EncryptString to encrypt Captcha text before passing it to GetImgText.ashx generic handler:
ImgCaptcha.ImageUrl = “GetImgText.ashx?CaptchaText=” + SecurityHelper.EncryptString(Captcha);
We also need to change GetImgText.ashx.cs to make it decrypt QueryString value:
var CaptchaText = SecurityHelper.DecryptString(
Convert.FromBase64String(context.Request.QueryString["CaptchaText"]));
This will make sure that nobody can sniff the captcha text. If you get the Captcha image properties in your browser, it will look like this:
http://localhost:51093/MyCaptcha/GetImgText.ashx?CaptchaText=V1rX8fZjL%2f8ghm1ZkCCsRoTryWDde8tJ7sejoIjoJKA%3d
I also tried to make the text more hard-to-read and a bit prettier so I changed the GetImgText.ashx file to draw an image background for Captcha. Background images come from /images/captcha folder so you need to create such a folder in your web site or modify the source code to point to an appropriate location. I have also added three sample background images, like a Valentine Day one:

try other background images and decide which one do you like the most.
Please visit CodePlex page of this project and download the source code.
How can I get this to work with Visual Studio’s CreateUserWizard?
I added a complete post in CodePlex about using MyCaptcha with CreateUserWizard control. Please read it here:
http://mycaptcha.codeplex.com/Thread/View.aspx?ThreadId=74794
Also, I was able to get your first version to function…just couldn’t get it working with the CreateUserWizard, but after downloading the updated files, I keep getting this error:
The name ‘SecurityHelper’ does not exist in the current context
Source File: MyCaptcha.ascx.cs Line: 55
Dear Steven,
SecurityHelper.cs is located under App_Code folder. Please add it to your own project. You can also replace it with any Encryption/Decryption utility.
Ah, I didn’t have SecurityHelper.cs in the App_Code folder! Thanks!
It’s not a problem with your code, I’m just not sure how to use it with CreateUserWizard, because I can’t just add the code in the wizard (& can’t add onclick to button). I was just hoping you or someone else has done it and could provide direction