Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Chess Steganography (incoherency.co.uk)
224 points by beardog on Jan 6, 2019 | hide | past | favorite | 48 comments


If anything the "one-sided" mode is even more fun: https://incoherency.co.uk/chess-steg/oneside.html

It lets you interactively encode a message in your moves when playing against a player who is not in cahoots with you :)

(Disclosure: I made this).

And yeah, sorry about the lack of error-checking. If pretty much anything goes wrong it (maybe) writes an error to the console, and just does nothing.

I'd be interested to see if anybody can produce a short message which can't be encoded because it results in a state where the only legal moves are checkmate.


I'd be interested in the shortest word that can't be encoded in the "one-sided" mode when playing against a strong AI. I played Stockfish as white while having black try to encode "hello" but Stockfish was able to checkmate black before it had finished.

https://lichess.org/yeg4eqyG


awesome, one just needs to consider to keep the message size below the expected move count for the game required for encoding


1. e4 g5 2. h3 c6 3. f3 Bh6 4. d4 Bf8 5. Rh2 b6 6. Ne2 Qc7 7. b3 f6 8. Ba3 Qg3+ 9. Kd2 a6 10. Kc3 a5 11. Nxg3 Nh6 12. Ne2 Kd8 13. Qe1 Rg8 14. Nf4 e6 15. Bb2 Kc7 16. Be2 Ng4 17. Ng6 Ne3 18. Qg1 f5 19. Ba3 Bg7 20. Nh8 Ng4 21. exf5 h5 22. Bd6+ Kxd6 23. Qc1 Bf8 24. Qb2 Ke7 25. Bb5 Ke8 { White resigns. } 0-1


1. c4 a6 2. Na3 a5 3. d4 b6 4. Nb5 d5 5. a4 dxc4 6. Bh6 Nxh6 7. Rb1 Ra6 8. b4 c5 9. bxc5 e5 10. Nd6+ Bxd6 11. cxd6 Qh4 12. dxe5 Ng8 13. Qc1 Bg4 14. h3 f5 15. Rb3 Nd7 16. Qd1 Bxe2 17. Kxe2 Nf8 18. f3 Qd4 19. g3 Qc3 20. e6 h5 21. Qc2 Qe1+ 22. Kxe1 b5 23. Qd1 Nxe6 24. Kf2 Nc5 25. Ne2 Rb6 26. axb5 a4 27. Rh2 c3 28. Kg2 Rc6 29. Kg1 Nd7 30. f4 g5 31. Qd2 Ne5 32. Qa2 Rh6 33. bxc6 c2 34. Rh1 c1=B { White resigns. } 0-1


Best. Phrase. Ever.


Was this meant to be in alignment with this person’s view point? http://amp.civilbeat.org/2017/05/hawaii-prof-to-white-guys-g...


It was a reference to https://en.wikipedia.org/wiki/Dirty_Hungarian_Phrasebook - no idea why I got downvoted ... perhaps Monty Python isn't appreciated outside the UK ?


Clearly not.


A dual to this is: how can you encode chess games in the smallest number of bits?

A move has one of 64 source squares and one of 64 destination squares, so that suggests a naive way to encode games using 12 bits per move. However, there are never more than 256 legal moves in any position, so we can improve on this by listing the legal moves in some reproducible order, then using 8 bits to pick one of them.

Of course most positions have far fewer than 256 legal moves. And some moves are more likely than others. So we can improve on this for real chess games (though not for random chess noise or the output of the chess steganography program in non-blunderfree mode) by sorting the moves in order of decreasing likelihood and doing some Huffman encoding so more likely numbers get shorter encodings. "Order of decreasing likelihood" is not trivial to define - even using a deterministic chess engine with a large depth would not necessarily be optimal, even putting aside performance concerns.

The state of the art in this is almost certainly the version used by Lichess https://lichess.org/blog/Wqa7GiAAAOIpBLoY/developer-update-2....


I published a blog post on this https://triplehappy.wordpress.com/2015/10/26/chess-move-comp... when I worked on the problem for my own chess GUI, it got some traction on hacker news. Funnily the Lichess blog post about their algorithm links to my article. Those guys are clearly much smarter than me - they jump straight to the optimal scheme without the painstaking exposition (and thinking) I needed :-) Basically about 2 bits per move is the best you can hope for, with aggressive and slow compression.


I'm not entirely understanding the motivation for this. The most naive method would be to just UCI move notation, that's simply square1-square2. Eg: e2e4 e7e5 g1f3, etc. That's 4 bytes per half move or ply (5 bytes for the once in a blue moon promotion). At an average of 80 ply per game, that's 320 bytes per game notation.

So if we have a billion games that'd just be 320GB. And as you mention converting this to binary yields 6 bits per ply, for a fraction of that. In other words you could naively encode every single game that's ever been played online, offline, or anywhere for a small fraction of the space on a regular large consumer HDD and still have plenty of space left for centuries of games to come. 20TB RAID kits go for less than $1k now a days. And you could load critical (likely to be accessed multiple times and/or concurrently) games (every game ever played by a very strong player, all games within the past year, etc) on a single SSD for rapid access.

Of course saving space is much better than not saving space, but the proposed method does not come for free. It involves some fairly complex heuristics. That means you're trading space for computational complexity. The former is practically free for things on this scale, but the latter very much is not. The article mentions that their decoder was only able to process around 1,111 games per second on average.

Lichess has been pushing around 40k players at some times and will presumably continue to grow. Performance this low on a critical and invokable task also seems to expose a clear denial-of-service vector. And adding new servers is vastly more expensive than adding some new hard disks. By contrast encoding and decoding games in UCI is practically free.

So what is the motivation here?


Agreed, I don't see the practical benefit here either, it's mostly interesting to me from an academic point of view. But we are after all in a thread about something with even less crowded practical value, hiding messages in constructed chess games.


Writing chess software as a hobby is relatively popular. And many people try to optimize as much as possible even when it's not strictly necessary. That's probably motivation enough - although lichess as a business probably doesn't have the same incentives as a hobbyist would.


Sure I completely get that, but what the core issue I was hitting on is that you end up trading an expensive resource (computing power) for a very cheap resource (disk space). In cases where disk space requirements become enormous this can be a necessary trade, but here that's not really an issue. I enjoy not strictly necessary optimization as much as anybody, but unless I'm missing something this optimization seems that it would ultimately result in a less performant system with very little to show for it so it wouldn't be particularly fair to call it an optimization.


Ah yes, but this way you get to write compression algorithms and do performance optimization. The journey is more important than the destination.

Edit: Also (in Lichess' case) you're not trading CPU usage for disk space, you're trading CPU usage for disk space and network traffic, which you're probably paying much more for.


> and doing some Huffman encoding so more likely numbers get shorter encodings.

Once you get a probability distribution over the moves, arithmetic encoding is the provably best (densest) way to encode them.


Amazing!

Small nitpick: I wanted to see the "hidden message" in The Game of the Century[0], but it says the last move is illegal:

    Illegal move played?? Rc2#
[0]: http://www.dwheeler.com/misc/game_of_the_century.pgn


That is intended behavior. Game ending moves are not allowed. See the explanatory blog post: https://incoherency.co.uk/blog/stories/chess-steg.html



You could then encode the chess notation in a video of two people playing a game of chess. How’s that for a hidden message?


The chess players in the video might be blinking "torture" though if it's a "no blunders" message.


Can we xor that with some atonal ambient music in the video for some kink?


The lichess link doesn’t work for me; is anyone else getting “Cross origin request forbidden”?


It broke for me in Chrome, but Firefox handled it just fine.


Broken for me on Safari Mobile


Getting it also


Same thing, just copy-paste the moves into https://lichess.org/paste


Errrr this type of stuff is the absolute bane of my Lichess rating


Just imagine AlphaZero romancing LeelaZero to plan an escape. That's probably why they didn't release a lot of games :)


Was hoping chessboard QR codes when I saw the title


Now there's an idea! Make it happen kylek!


this is really cool on so many levels - this could lead to a general turn based game playing steganography - like go, poker etc? just need a little more time :)


This is pretty fun. You might run into a useless result, such as "Hi, I'd like to buy some weed." without blunders translating to a 369 move game, but if you have the freedom to experiment with minor variations, you can find one that works. "Hi, I'd like to buy some weed" is only 41 moves.


So, I'd don't have a board readily available and don't know the notation to well. But does "resign" mean give up in this context? Would it be possible to make this actually run into chess mates at the end of the message?


> does "resign" mean give up in this context

Yes.


Lol. You can put stenography in any noisy information channel.


I wonder if theres an anti steganography move pattern to obfuscate your opponents move. Or do you just win quickly to avoid them sending a useful message?


I tried it but it slowed down my browser and capped my CPU so i had to stop.


very cool!

ps- got a cors issue on the “view on lichess”


I've just tried to unsteg one of my real games to find out if I had anything smart to say, but got "chess-steg.js:139 Uncaught URIError: URI malformed"


So if chess-steg were written in C, one could play a chess game with a malware bootstrap payload!


This seems fairly pointless


Yeah... I had thought that this would be a good way to share messages secretly, but the thing is the moves are nonsensical, so anyone who bothered to check out what the game progresses would know something is up and would google "Chess message encoding" (the fifth result is the blog post for it, lol).

If the moves actually made sense, this would be a lot more useful. There's probably something that can measure how good a move is, so I guess what you can do is make sure that the moves you use to form a message are above a certain threshold. That way, someone looking into the moves wouldn't immediately know that they're being used to encrypt messages. But honestly other than that, I dunno what you can use it for.


What you describe is exactly what the "without blunders" mode attempts to do, but evaluating every possible move for each player to a useful search depth takes a long time, so it doesn't search very far.

Also, the more you restrict the space of allowable moves, the more moves are required to encode a given message.


Oh I didn’t notice that option, cool.

By the way, what was your motivation for creating this?


It's just a fun & interesting idea.


That's what hacking is all about!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: