The crossword is trivial, I was able to guess each word on first attempt, except the last long word. Instead of thinking about it, and realising that several others had already done it, I thought I'd have a look at the code.
It turns out that the code is somewhat smart and doesn't reveal the words, rather it uses a custom hashing algorithm and stores the hashes. The two pieces of JavaScript controlling the crossword are the configuration (questions & answers) and the functionality. There are two interesting pieces of information in these, the first is the hashes of the answers stored in the configuration:
AnswerHash = new Array(10664, 37493, 27958, 81424, 27548, 67695, 31280);
And the second, in the functionality, is the hashing algorithm:
function HashWord(Word)
{
var x = (Word.charCodeAt(0) * 719) % 1138;
var Hash = 837;
var i;
for (i = 1; i <= Word.length; i++)
Hash = (Hash * i + 5 + (Word.charCodeAt(i - 1) - 64) * x) % 98503;
return Hash;
}
A quick look at the hashing algorithm shows that it probably isn't reversible (or at least not trivially), primarily due to the modulus operators which aren't reversible. However, all is not lost, the algorithm is very simple, which means two things. The first is that it will have a ton of collisions (i.e. many words will result in the same hash) and the second is that your processor won't do much work in running it. Thus, I figured it may be fun to run it across a dictionary and see what collisions pop-up.
Since I was playing, I decided to check out whether there were any CLI JavaScript shells that I could use, and the speed at which they run. A quick google showed me that Chrome's V8 JavaScript engine has a "toy" shell that could be used. I pulled down the trunk, and with the sample=shell option passed to scons had the shell binary built.
The V8 shell is pretty cool, and can either be run interactively, used to evaluate JS passed as an argument with the -e switch, or run multiple files. However, input via CLI can't be passed as an ARGV, and either needs to be in one of the files, or in a -e statement. So I created three files:
- hash.js - Which contained the HashWord function above verbatim, but with a toUpperCase() added to the word passed
- dict.js - Which contained /usr/share/dict converted into a JS Array object
- loop.js - Which contained the answer hashes array, and looped through the dict comparing resulting hashes to the answers
If you're interested, the three files can be downloaded from here. They can be run by passing all three as arguments to shell e.g. ./shell dict.js shell.js loop.js
The results were as follows:
Found! Word: anonymous Hash: 27958
Found! Word: coseismic Hash: 10664
Found! Word: cryptanalysis Hash: 31280
Found! Word: Cupressaceae Hash: 27548
Found! Word: cystolithic Hash: 31280
Found! Word: honeypot Hash: 37493
Found! Word: irrationability Hash: 10664
Found! Word: miscommit Hash: 37493
Found! Word: phloroglucic Hash: 10664
Found! Word: pneumotoxin Hash: 67695
Found! Word: psychics Hash: 10664
Found! Word: reeky Hash: 67695
Found! Word: rhamphoid Hash: 37493
Found! Word: shuckpen Hash: 81424
Found! Word: stowbordman Hash: 81424
Found! Word: unthoughtedly Hash: 27958
Out of interest the result of time() were: 0.39s user 0.06s system 97% cpu 0.460 total
If you've checked the crossword, you'll see some of the answers are listed, you'll also see that there are several collisions, for example 'cryptanalysis' and 'cystolithic' both result in 31280, the hash of the final 'secret' word. It was fairly obvious that 'cryptanalysis' was the final word (apart from being the right length, it's the only security related term) however, I then tried to see if one of the 'incorrect' collisions would work. Unfortunately, there is a length check and so a straight substitution doesn't work, but 'coseismic' in the place of 'conficker' is accepted by the crossword as this image shows:
However, when you try and complete the crossword with the incorrect word, the 's' in 'coseismic' conflicts with the 'c' in 'cryptanalysis' and so you can't complete the crossword with this combination of words. However, if you don't limit yourself to english, and rather use random characters, you could eventually find gobbldegook that would complete the crossword. A challenge for someone else perhaps?
So that's my hackers attempt at 'cracking the code'. Hope to see you at the summit.