Threema Encryption Validation

Threema contains a "Validation Logging" feature that makes it possible for anyone to independently confirm that messages sent via Threema are end-to-end encrypted using the NaCl Networking and Cryptography library. It works by logging the raw encrypted message as it was generated by the sender to a text log file that can be emailed from within the app. Using the sender's public key and the recipient's private key, the message can be decrypted by a very simple decryption program written in C that is supplied in source code form.

Prerequisites

The supplied C programs have been verified to compile under Linux and FreeBSD. If you don't have access to a physical machine with one of these operating systems installed, we recommend that you install Ubuntu Desktop as a virtual machine.

Some knowledge on using a Unix-type operating system is required, and knowledge on how to operate a C compiler may be necessary. Verification of the source code of the supplied C program requires working knowledge of the C language.

Preparation

Installing NaCl

The decryption program requires an installation of the NaCl library. For common operating systems, a ready-made package is available from the vendor.

If no package is available for your operating system, you can also compile NaCl from source as described on the NaCl Installation page.

Downloading and compiling the programs

Download the source code of the validation programs.

The following files are included:

Usually all that is required to compile threema_unbox and threema_getprivkey is to type make inside the directory with the files.

Obtaining the private key

Your raw private key can be extracted from a Threema ID backup (a string in the format "ABCD-EFGH-IJ12-..."). Use threema_getprivkey as follows:

# ./threema_getprivkey
backup: 7MUX-MA7U-MOED-JG5T-ZXNX-EMAQ-IZKE-JXXM-RT3D-K3LN-UZA7-JJWF-3OTB-YSKP-XW3I-HG6I-UKJM-75R2-2PAK-HIAD
password: <enter backup password>

Identity: STUVWXYZ
Private key: aaebd94ed62dbbf21f557c9af485a6a27f39e7663d8024a3aba46b70bf50c670

IMPORTANT: keep the private key confidential and destroy it after use!

Obtaining the public key (optional)

Message decryption also requires the public key of the message's sender (for incoming messages) or recipient (for outgoing messages). For convenience, the validation log already includes the public key. If you want to be extra sure, you can obtain it from the QR code displayed by the other person's Threema app (note that it has to be the other person's public key, not your own!).

Scan the QR code using a generic QR scanner app, e.g. NeoReader. You will get a string like the following:

3mid:ABCDEFGH,9246c8107a8c3b71a9ffc845db2b463a3b3b73d4d6b133fa8673eefb0bae3f69

The public key is the 64 hex characters at the end of the string.

Decrypting a message

The validation log will contain entries like the following (note that this is dummy data and will not decrypt):

2013-03-13 16:54:58 +0000 incoming message ID 0123456789abcdef from ABCDEFGH to STUVWXYZ:
Nonce: 9ed4f34a8c97e7410f43e4286e241620331be3a14d892e9d
Data: 140733c4b99d1ea6e75fc1debbe377f0455674734fdb57505be6dfde94fcf03ea80a12472
c908a37ce5efad9883701e5bd570fb588670c41b6df5f3bf37835136b0369ba6ae2835233d904d2
842716e651fd0bd401d7cb02dac232021e138688f84ec6043bfccbff7543a69077b4fcf94f77420
8a85dbc12c86556af8ba3becff05e45b24a0f851ba66f4d38a071663a276
Public key (ABCDEFGH): 9246c8107a8c3b71a9ffc845db2b463a3b3b73d4d6b133fa8673eefb0bae3f69

Choose the message that you want to decrypt. Start threema_unbox and provide the following values (all in hex):

# ./threema_unbox
nonce: 9ed4f34a8c97e7410f43e4286e241620331be3a14d892e9d
pubkey: 9246c8107a8c3b71a9ffc845db2b463a3b3b73d4d6b133fa8673eefb0bae3f69
privkey: aaebd94ed62dbbf21f557c9af485a6a27f39e7663d8024a3aba46b70bf50c670
data: 140733c4b99d1ea6e75fc1debbe377f0455674734fdb57505be6dfde94fcf03ea80a12472
c908da37ce5efad9883701e5bd570fb588670c41b6df5f3bf37835136b0369ba6ae2835233d904d
2842716e651fd0bd401d7cb02dac232021e138688f84ec6043bfccbff7543a69077b4fcf94f7742
08a85dbc12c86556af8ba3becff05e45b24a0f851ba66f4d38a071663a276b0664cfa

Padding: 113 bytes

Sample message text.

If decryption is successful, the number of padding bytes included in the message will be printed, followed by the message text (each message contains a random amount of PKCS#7 padding). The length of the encrypted data equals ([type = 1 byte] + [authenticator size = 16 bytes] + message text length + padding).

A note on outgoing messages

It may seem strange that outgoing messages can be decrypted by entering the sender's private key and the recipient's public key, i.e. without knowing the recipient's private key. This is because NaCl uses ECDH to derive a shared secret between the two involved parties, which is then used in conjunction with a nonce for symmetric encryption. The secret is the same no matter whether the combination of (sender private key + recipient public key) or (sender public key + recipient private key) is used. This behavior is also the reason for the repudiability property of the NaCl crypto_box model: using his own private key and the sender's public key, any recipient can forge a message that will look just like it was actually generated by the purported sender, so the recipient cannot convince a third party that the message was really generated by the sender and not forged by the recipient. However, the recipient is still protected against forgeries by third parties, since the recipient himself will know whether or not he has used his own private key for such a forgery.