Chainzilla — NEM cryptopuzzle write-up

pogo
6 min readDec 8, 2018

--

Chainzilla — NEM cryptopuzzle, created by cehhiro

Original links:

https://twitter.com/Chainzillaio/status/1071065610552045568

https://medium.com/chainzilla/nem-cryptopuzzle-b2dfad0c3e32

As the article above says, the puzzle image holds the private key to a wallet, with no additional confirmations or steps along the way. A first look at the image should be enough for us to guess that the grid of 32 characters in the middle should be a good starting point. Since we know a private key is 32 bytes, or 256 bits, a good guess is that each character encodes 8 bits of information. Also noticeable is the fact that we have 16 NEM logos, with different rotations, all of them connected with arrows to 1 or 2 of the other logos. This is hinting towards a certain path (+ rotation?) to be taken after we have the data.

We should also note the address of the prize wallet, which can be found from the transaction given in the medium article (by looking at the recipient):

NB7NH7-TQ3XA3-APR77C-XWAPWP-UJSBNF-2T4YFQ-YDPJ

The grid

First we would like to get that data from the grid. There’s more than just the ASCII symbols in there so we to find an encoding which holds everything we see. A search of different charsets reveals that the characters used belong to the ISO-8859–1 ( https://en.wikipedia.org/wiki/ISO/IEC_8859-1 ) otherwise known as the Latin 1 charset.

The one extra problem we’re faced with is identifying exactly what each character is. The font used is rather odd and there are several ambiguous symbols, such as the rectangle in the top right corner, the “1” or “l” on line 3, last column, the dash (there are two dashes in the Latin-1 charset), as well as a few others. So it would be a big help if we could identify the font used and generate all the printable characters with it, for comparison. There are probably several ways to find fonts, but the way I did it was simply to grab another image which I was sure contained the same font and used an online tool for font detection (since this puzzle’s image resolution was pretty poor).

Grid symbols transformed to byte values

The font used turns out to be https://fonts.adobe.com/fonts/ocr-a . From this link we can also directly play with all characters and find the unique symbols for each grid cell. Armed with all this information we can determine the contents of all the cells in the grid. So now we have all the bytes that go into the private key, but testing this will not give the correct address, because there’s a bit more work to do.

The path

Now the next part was fairly straightforward. Looking at the puzzle image, we can see that there are 16 NEM logos and that there are some arrows that are connecting them. A careful eye will find that most of the logos have both an “in” and an “out” arrow, with a single logo (first row, first column) having only an “out” arrow, while another logo (second row, last column) has only an “in”. Since there’s also 16 cells in the grid, this clearly traces a path for us in which to “collect” each group of 2 bytes obtained until now.

Path and rotation

Using the path marked by the arrows, the byte values that we obtained above should give

3BF72D563A6BBFAC2C54A57B45D06657F8632EE14C2B7E417031DFAA263063FE

which, if tried as a private key, will still fail to give the correct address of the wallet.

The Rotations

Now on to the last part, which was the trickiest. We can clearly see that the NEM logo appears 16 times, which is the same as the number of cells we have in the grid. We can also see that the logo is rotated by a certain amount in each position. Well, if we try to quantify this (see image above), it turns out there’s only a total of 8 rotations used, which roughly cover 360 degrees, even though they most likely aren’t finely tuned. The only external information that we need to know is how the NEM logo looks like in its default position, since we know that will be rotation 0.

NEM logo

Thanfully, this can be found out very quicky with a simple search, so now we have both a starting point and a quantized rotation, so we can extract a set of 16 values between 0–7, which we’ll probably have to use on the private key. There is just one thing missing, and that is, the direction of rotation. As far as I can tell, there is no clue which tells us if we should take the rotation as clockwise or counter-clockwise . Not a huge problem, though.

For reference, the string of rotations that I obtained while going along the arrow path is 3575722811463717 (which corresponds with the image above), but realizing that I should have started the indexing at 0, subtracted 1 from all numbers to obtain 2464611700352606. Since we need both rotations, we can build the values for the rotation in the other direction by simply taking (8-digit(i)) % 8 for each digit from the previous string, to obtain 6424277100536202.

Now, there’s still the issue of what to do with the rotations, and I’m guessing this is where some people were getting stuck. For a few hours I thought that we should split each cell that holds 2 bytes (16 bits) into 8 slices of 2 bits, and rotate them around (basically like a circular shift but with 2 bits as the smallest part of the information). I tried everything related to it with no luck. Dropped it and played a bit before bedtime, but before calling it a night I figured I might as well try real circular shifts ( https://en.wikipedia.org/wiki/Circular_shift ), simply because I had a script written that did exactly this a while ago and knew it wouldn’t take long. Well, we don’t know if we should shift left or right, and we don’t know which way the rotation on the logo is counted, so actually we will have to generate a total of 4 private keys. Not that terrible, since the circular shift step was probably intended to be coded (at least I wouldn’t have the patience to do it by hand…)

The Solution

Spoiler: the circular shift idea mentioned above worked! So, take each decoded cell along the path indicated by the arrows and then circular shift it by the amount indicated by the logo rotation for it.

Starting from the basic key obtained before, by following the path, the following 4 private keys are generated:

EFDCD5629ACEFACB150B4AF78BA02BB3F8632EE1615AC82FC0C5EAB72630FF98
CEFD62D5ACE9CBFA50B1D2BD22E8AECCF8632EE169850BF25C0CAB7E2630F98F
FDCED562E9ACFACBB150BDD2E822CCAEF8632EE18569F20B0C5C7EAB26308FF9
DCEF62D5CE9ACBFA0B15F74AA08BB32BF8632EE15A612FC8C5C0B7EA263098FF

And if you just give them a try…. you’ll find that the 2nd private key generates the correct address for the prize wallet! YAY!

Acknowledgements

My thanks goes out to Chainzilla and NEM for sponsoring and setting this puzzle up, as well as to Cehhiro for creating it. Thanks to Robin Jadoul and LeFevre for discussions that helped in the solving process.

You can go check out the Chainzilla discord community here:

https://discord.gg/QMSgXvs

For some great, active puzzle comunities, check out:

Crypto_puzzles: https://discord.gg/bSn85h5

ARG Solving Station: https://discord.gg/uYAXsww

Neon District: https://discord.gg/RB7pKHz

--

--

No responses yet