Create a Captcha With SwiftUI
By: Mark Lucking
Tags: Swift, Mobile, Swiftui, iOS, Programming

Create a Captcha With SwiftUI

An example of a captcha. GIF by the author.

Trying to figure out if you’re talking to a human being or a bot these days is becoming increasingly difficult. In recent years, the de facto method to solve this has been a captcha — a challenge/response protocol that either gives you a set of images and asks you to identify something within some of them or a string of text that has been distorted (as shown above).

I am going to focus on the latter in this article. We’re going to try to disguise a string of text such that a human can still figure out what it says, but a bot will struggle. I will present a solution to do so in SwiftUI.

Where do we begin? I published a couple of articles a while back on rotating images. They talked extensively about the rotationEffect , which is a possible starting point. I can turn and twist the numbers and letters in my text and produce a captcha version:

The hexidecimal alphabet being captcha’d with rotation3DEffect

In this GIF, I have flipped the letters on every axis randomly, although I have limited the angle to 65% degrees to keep it readable. It’s OK but leaves a good deal of room for improvement. One of the gotchas I already have to solve here is the fact that the letters remain with their own space, which is a real giveaway for a bot trying to analyze what it is looking at.

Now the answer lies in the Core Graphics framework, an aspect of which is accessible within SwiftUI constructs. A method whose roots lie in the branch of mathematics called Affine geometry. It is specifically available within SwiftUI with the transformEffect tag.

You have five transformations possible with Affine geometry:

Translations, which is simply moving the X and Y origin.

Reflections, which is a mirror image.

Scaling, which makes it larger or smaller.

Rotating, which is doing just that.

Shearing, which is the one we’re really interested in.

Shearing an image will distort or warp it. This is important for our captcha because the human brain is good at correcting this sort of thing, but your average bot isn’t. Coincidentally, I wrote an article last week about the sort of shape that a shearing an image produces. It is known as a trapezoid.

To the code. What does this all mean and how does it work? Understanding offline transformations is quite easy if you have a template.

This is called the identity matrix — a matrix that represents the image as it appears without any transformations. Now by changing the values held in the different positions, you effectively describe how you want to change the affine space it refers to.

For example, with code, we can define a shear transformation of ten degrees:

The letters map across to the matrix I presented earlier. Using warping, we can create a far wilder captcha (the one presented at the beginning of this article). Note that I took the values needed here from the Wikipedia page of templates.

All of this brings me to the end of this short article. Here is the iOS code you need to do all the different sorts of transformations using Core Animation:

But wait, just before I go, there are two other tricks to the trade here.

The first is to use a font that is hard to read anyway. It sounds a little daft, doesn’t it? But if you think about the task at hand, it makes sense.

The second is to introduce noise into the picture — enough to confuse an image-processing algorithm but not so much that you cannot read the text. It’s a fine line I will leave you to explore.

Keep calm, keep coding.