using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Security.Cryptography;
public class Turing : System.Web.UI.Imaging.ImageGenerator
{
#region Randomized Data
private static string[] fontNames = new string[]
{
"Arial",
"Comic Sans MS",
"Courier New",
"Lucida Console",
"Tahoma",
"Times New Roman",
"Trebuchet MS",
"Verdana",
};
private static Color[] backColors = new Color[]
{
Color.Beige,
Color.AliceBlue,
Color.AntiqueWhite,
Color.WhiteSmoke,
Color.White,
Color.FloralWhite,
Color.Linen,
Color.OldLace,
Color.LightYellow,
Color.MistyRose,
Color.MintCream,
Color.LightCyan,
Color.Azure
};
private static Color[] foreColors = new Color[]
{
Color.RoyalBlue,
Color.DarkMagenta,
Color.Teal,
Color.ForestGreen,
Color.Goldenrod,
Color.Sienna,
Color.Firebrick
};
private Color randomForeColor()
{
return foreColors[random.Next(0, foreColors.Length)];
}
private Color randomBackColor()
{
return backColors[random.Next(0, backColors.Length)];
}
private Brush randomSolidBrush()
{
return new SolidBrush(randomForeColor());
}
private Pen randomPen()
{
return new Pen(randomSolidBrush());
}
private string randomFontName()
{
return fontNames[random.Next(0, fontNames.Length)];
}
#endregion
private static Rijndael rijndael;
static Turing()
{
rijndael = Rijndael.Create();
rijndael.GenerateKey();
rijndael.GenerateIV();
}
///
/// Sets the image height.
///
protected override int DefaultHeight
{
get { return 30; }
}
///
/// Sets the image width.
///
///
protected override int DefaultWidth
{
get { return 120; }
}
#region Painting Code
private Random random; // Use a single random instance so we don't get the same values on fast processors
protected override void RenderImage(Graphics g)
{
// Get the string to render
byte[] nonce = Convert.FromBase64String(Request.QueryString["nonce"]);
string str = decrypt(nonce);
this.random = new Random();
// Set pretty quality
g.SmoothingMode = SmoothingMode.AntiAlias;
g.CompositingQuality = CompositingQuality.HighQuality;
drawBackground(g);
// Changing these around allow the lines to be drawn under the letters
drawLines(g);
drawLetters(g, str);
}
///
/// Creates a psuedo-random background.
///
private void drawBackground(Graphics g)
{
g.Clear(Color.White);
// Some code to play with to get coloured backgrounds.
// Also check out using a HatchBrush for added fun.
/*Color backColor1 = randomForeColor();
backColor1 = Color.FromArgb(96, backColor1.R, backColor1.G, backColor1.B);
Color backColor2 = randomForeColor();
backColor2 = Color.FromArgb(96, backColor2.R, backColor2.G, backColor2.B);
LinearGradientBrush b = new LinearGradientBrush(
new Point(0, 0), new Point(DefaultWidth, DefaultHeight),
backColor1, backColor2);
b.RotateTransform(90);
b.ScaleTransform(.3f, .1f);
g.FillRectangle(b, 0, 0, DefaultWidth, DefaultHeight);*/
}
///
/// Draws the string's letters in a psuedo-random looking way.
///
private void drawLetters(Graphics g, string str)
{
int currentX = random.Next(5, 15);
for (int i = 0; i < str.Length; i++)
{
string currentChar = str[i].ToString();
// new randomized font
Font font = new Font(
randomFontName(),
random.Next(16, 20),
GraphicsUnit.Pixel);
g.DrawString(currentChar, font, randomSolidBrush(),
currentX, random.Next(0, 10));
// increase starting point
currentX += (int)g.MeasureString(currentChar, font).Width;
currentX += random.Next(0, 5);
}
}
///
/// Draws some random lines on top of the output.
///
private void drawLines(Graphics g)
{
int numLines = random.Next(3, 5);
for (int i = 0; i < numLines; i++)
{
Pen p = randomPen();
p.Width = (float)((random.NextDouble() + 0.1) * 2.5);
g.DrawLine(p,
random.Next(0, DefaultWidth), random.Next(0, DefaultHeight),
random.Next(0, DefaultWidth), random.Next(0, DefaultHeight));
}
}
#endregion
///
/// Creates a
///
///
///
private static string encrypt(byte[] input)
{
byte[] enc = rijndael.CreateEncryptor().TransformFinalBlock(input, 0, input.Length);
return Convert.ToBase64String(enc);
}
private static string decrypt(byte[] nonce)
{
byte[] dec = rijndael.CreateDecryptor().TransformFinalBlock(nonce, 0, nonce.Length);
return System.Text.Encoding.ASCII.GetString(dec);
}
public static string GenerateNewNonce()
{
// First come up with 5 capital ASCII letters
byte[] input = new byte[5];
Random r = new Random();
for (int i = 0; i < input.Length; i++)
{
input[i] = (byte)r.Next(0x41, 0x5A);
}
// Encrypt them
return encrypt(input);
}
public static bool Verify(string nonce, string input)
{
byte[] inData = System.Text.Encoding.ASCII.GetBytes(input);
return encrypt(inData) == nonce;
}
}