Hackernoon logoHow to Make a Captcha in Python by@manushifva

How to Make a Captcha in Python

image
manushifva Hacker Noon profile picture

@manushifvamanushifva

just ordinary manushifva

Captcha is becoming complex and impractical with time. Here is an example:

image

So, I dedicated myself to make my own captcha system that's more practical. At first, I needed some idea for the captcha, and here it is:

image

I used Python to build the captcha system. Here is the snippet:

import random, string
from PIL import Image, ImageDraw
import numpy as np

bomb = Image.open("bomb.png")

bomb = bomb.resize((round(bomb.size[0] * 0.5), round(bomb.size[1] * 0.5)))
bombMask = bomb.convert("L")

lock = Image.open("lock.png")
lock = lock.resize((round(lock.size[0] * 0.5), round(lock.size[1] * 0.5)))
lockMask = lock.convert("L")

def randomName():
    strData = string.ascii_letters + string.digits
    response = ''
    for x in range(16):
        response += random.choice(strData)

    return response

def buildCaptcha():
    bgColor = (random.randint(200, 255), random.randint(200, 255), random.randint(200, 255))
    img = Image.new('RGB', ((bomb.size[0]) * 5 + (40 * 6), bomb.size[1] + round(bomb.size[1] * 1.5)), color = bgColor)

    result = []
    posX = 40
    maxHeight = 0
    for x in range(5):
        num = random.randint(1, 2)

        rotateDeg = random.randint(0, 360)
        if (num == 1):
            result.append(0)
            thisImg = bomb.rotate(rotateDeg, expand=1)
            thisMask = bombMask.rotate(rotateDeg, expand=1)
        else:
            result.append(1)
            thisImg = lock.rotate(rotateDeg, expand=1)
            thisMask = lockMask.rotate(rotateDeg, expand=1)

        num = random.randint(1, 3)
        if (num == 2):
            thisImg = thisImg.transpose(Image.FLIP_LEFT_RIGHT)
        elif (num == 3):
            thisImg = thisImg.transpose(Image.FLIP_TOP_BOTTOM)

        thisImg = thisImg.convert('RGBA')
        data = np.array(thisImg)
        red, green, blue, alpha = data.T
        white_areas = (red == 255) & (blue == 0) & (green == 0)

        itemColor = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
        if (itemColor == bgColor):
            itemColor[0] = random.randint(0, 255)

        data[..., :-1][white_areas.T] = itemColor
        thisImg = Image.fromarray(data)

        img.paste(thisImg, (posX, 50), thisMask)
        posX += lock.size[1] + 40

    draw = ImageDraw.Draw(img) 
    for x in range(random.randint(50, 80)):
        draw.line((random.randint(0, img.size[0]),random.randint(0, img.size[1]), random.randint(0, img.size[0]), random.randint(0, img.size[1])), fill=bgColor,  width=random.randint(3, 5))
        
    for x in range(random.randint(50, 200)):
        dotX = random.randint(0, img.size[0])
        dotY = random.randint(0, img.size[1])
        diameter = random.randint(1, 10)

        draw.ellipse((dotX, dotY, dotX + diameter, dotY + diameter), fill=(random.randint(0, 255), random.randint(0, 255), random.randint(100, 255)))

    for x in range(random.randint(15, 30)):
        draw.line((random.randint(0, img.size[0]) , random.randint(0, img.size[1]), random.randint(0, img.size[0]) + 20, random.randint(0, img.size[1])), fill=(random.randint(0, 255), random.randint(0, 255), random.randint(100, 255)),  width=random.randint(1, 3))

    filename = randomName() + '.png'
    img.save('captcha/padlock/' + filename)
    file = open('answer.csv', 'a')
    file.writelines(' '.join(str(v) for v in result) + ',' + filename + '\n')

So, what the system does is:
1. Read the source images,

bomb.png
and
padlock.png.

2. Create the background image with a random color.
3. Generate the random icon.
4. Change the icon color with a random color.
5. Add some random lines and dots.
6. Save the image with a random name.
7. Store the file location and captcha answer in a file named
answer.csv
.
8. Repeat it 1000 times.

Here is the result:

image

And here is another sample:

image

After that, we need the engine and user interface for the captcha. For the engine, I used PHP with MySQL database, and for the user interface, I used bootstrap. Here is the engine work:

1. Read the

answer.csv
to receive random captcha location and the answer.
2. Store the answer to the database, and add the unique hash for the identifier.
3. Give the unique hash, and file location to the UI.
4. The UI process the data and turn back the user response with a unique hash (of course) to the engine.
5. The engine checks the answer.
6. If valid, the engine updates the captcha data, sets it as solved. If it's not valid, the engine will try the process 'till 3 times.

Here is the final result:

Before submission:

image

Captcha authentication process:

image

On success:

image

On fail:

image

This is my first article! Thanks for reading. Have a good day.

Tags

Join Hacker Noon

Create your free account to unlock your custom reading experience.