Next article: Friday Q&A 2011-12-02: Object File Inspection Tools
Previous article: No Article For you!
Tags: meta
Due to a recent uptick in spam comments (I've had to delete literally several this week!) I decided to dust off my dormant JavaScript-based hashcash implementation and drop it into the comments system as an added anti-spam measure.
In short, hashcash is a scheme that uses a problem that's difficult (but not too difficult!) to solve but easy to verify to prove computation. In this particular case, the problem is producing data whose SHA-1 hash contains a certain number of leading zeroes.
When you click in any of the comment fields, the JavaScript fetches a unique salt from my server. It then begins a brute-force computation, searching for data which, when appended to that salt, produces the requisite number of leading zeroes in the SHA-1 hash. Once it finds one, it saves that value and enables the "Post Comment" button. The required number of leading zeroes is configured to take, on average, a reasonable amount of time to compute. This time is large enough to deter spammers trying to post stuff immediately, but small enough not to get in the way of legitimate users. It's currently configured to use 18 leading zeroes, which gives a roughly 10 second computation itme on a modern Mac.
On the server, the story is much simpler. All it has to do is keep track of the hashes that it gives out, and verify the hashcash that comes back in. Verification is simply a matter of checking that the salt is one it previously gave out, and checking that the salt + hashcash does indeed produce an SHA-1 hash with the required number of leading zeroes. While it takes several seconds of computation to produce the hashcash, it is essentially instantaneous to verify, producing no real server load.
Note that this scheme also works fine on iOS devices, but takes somewhat more time to compute the hashcash. It should still take much less time than it takes to compose a good comment, though!
For those of you worried about battery life, the hashcash computation only kicks off when you actually focus one of the comment form fields, so simply reading a blog post doesn't add any additional load.
Please feel free to play with the new system in the comments to this post. I hope that it will deter spammers while not impacting legitimate commenters. Also, it was fun to write.
Comments:
As it happens, doing it in JavaScript is about 100x slower than doing it in C using CommonCrypto, so that certainly could be done here. But you'd have to dedicate quite a bit of development time developing a special client just for my blog comments, and at that point I'm not really going to worry about it too hard.
document.forms[0][0].onfocus();
document.forms[0][0].value = "spam";
And then just wait for the "Post Comment" button to become available. Since you've already implemented the JS to actually do the computation, there isn't any added complexity to the "spam" client.
I would think this is about as good as just having a hidden field you expect to be a certain value, that JS fills in that value onfocus()
This also hits human spammers, who have similar time constraints. They'll want to open the page, paste paste paste submit, all really quickly. This forces them to wait.
As a bonus, it also discourages legitimate commenters with nothing important to say.
Your idea is interesting, but at best is a nuisance for spammers. At worst, a nuisance to spammers AND nuisance to your readers.
How could it be a nuisance to my readers? If you mean because it prevents people from being able to write and submit a post in under 10 seconds, well, that's just the sort of nuisance I want to give to my readers.
I really should check my logs for the IP address that spam comments come from and see if the requests show anything about the nature of what's posting them. I'll have to remember to do that next time one shows up.
On a small blog like this, any custom solution is enough to cut down on spam substantially, at least for a long time, because it's just not worth it to write any custom code for it, no matter how easy.
As JavaScript engines improve (and I assume that crypto will be a particularly important target for optimization), that will allow the hashcash difficulty to be turned up, lessening the advantage of a native implementation. So it could become a truly useful, scalable solution eventually.
Hashcash is only one valid client puzzle, among many though. For Wordpress, there is a "hashcash plugin", but when you look at the source, it's actually not Hashcash. Instead, it's just a random client puzzle. But, proof-of-work client puzzles work all the same.
Well done on implementing Hashcash though. If more people would do this for their web applications, we wouldn't need those ridiculous CAPTCHAs.
Comments RSS feed for this page
Add your thoughts, post a comment:
Spam and off-topic posts will be deleted without notice. Culprits may be publicly humiliated at my sole discretion.