Every Sunday, I work on open-source software for the Dutch table tennis federation: NTTB. And in the evening, I have a call with another developer to discuss our progress and decisions. Where I have more software knowledge, the other is far more knowledgeable in the Sport than I ever will be.
The Table Tennis Tournament, aka T3, is built to be used by any table tennis federation around the globe. And the most important thing is trust. Tampering with the data must be strictly forbidden. I don’t trust the application that the user runs, the server, the database, or myself. Any change to the data that represents the outcome must be proven. And the only proof I will accept is cryptographic proof.
Luckily, in this day and age, we have plenty of solutions to work with cryptography. We can encrypt, decrypt, sign and verify data. And this solved one problem: The users will create a private key that signs the data, and an associated public key verifies that it wasn’t tampered with. Any change that the server (or the clients) receive will consist of the payload (“change score to 2-4”) and a signed version. And any future changes will use the previous payload to prove it’s authentic.
At the end of a match, both players must sign off on the captured results: Confirming that they have won/lost with a given score. With pen and paper, this requires an autograph, but in the app, this requires a private key that nobody but the user should have. Of course, keys can be stolen, but because we know which public key was used, we also know which other matches might be compromised.
This idea worked incredibly well, so more features were added: Asking for a timeout, changing sides, changing the server, and so on. Since the server only receives and forwards data, it was pretty simple to add new data structures to it. That was until I started working on penalties.
Like most sports, you can be penalized when you perform an offense. This is also true for table tennis: A player can receive a yellow card as a warning and a red card when the player is ejected from the game. However, only the matches with an official NTTB umpire/referee can do that. Sufficient to say that I don’t know all the ins and outs of that. Luckily we have access to someone who does.
First of all, the penalty card (yellow, red, or both simultaneously) requires some paperwork. The umpire/referee (note that these are different roles) must also explain the reason for the penalty. Most of the time, a code is used. For example, cursing at the referee is a code 3. These codes are public information, but any additional details a referee adds must be hidden and only available to certain parties (like the discipline committee).
So far, the server has received and shared information with other parties without changing anything. It didn’t add/remove information. However, we don’t want the entire world to know what/why the umpire/referee made a decision. So we need secrets.
And this is my goal today, adding cryptographic secrets that can only be shared with those who need them. There are two ways of doing that: Encrypting parts of the payload, but those events are shared with everyone, so people might not know the content but can still know when the data was changed. A referee might change the wording of a penalty event. It would be very understandable if a referee/umpire might write something less savory (for example: “The idiot kicked the table and now requires medical attention”). Usually, such remarks might appear in their private log, but the official statement must be more professional. Also, we might not want that, with the nature of the application, this would be shared instantly, encrypted or not.
Instead, I have decided on private notes that can be added or removed. I wanted to use this for other things where two parties needed to make a decision upfront but not share it without the other party knowing it.
At this point, there is only one disadvantage: How should the decryption keys be shared? After all, I develop the application assuming I might be a bad actor. So what can I do to prevent people from using my keychain to share keys? Luckily we have something called ECDH, that way, only two parties can decrypt the notes, which means that the only option left is a men-in-the-middle attack, but this can be detected because all the messages are signed with a public key. Thus any client can notice that the communication was compromised.