It’s so dark, that it is not even implemented (yet) Part I


DIME has been publicized a lot since last January. I’ve been reading the specs document (from 2015) and I have cloned the git repository in order to compile and test MAGMA, their open source server. This server, at least in theory, implements SMTP, IMAP, HTTP, MOLTEN, DMTP and DMAP. But of course, according to github:

The magma server daemon, is an encrypted email system with support for SMTP, POP, IMAP, HTTP and MOLTEN,. Additional support for DMTP and DMAP is currently in active development.

Anyway, I thought it would be interesting to test it because, although I suspected that maybe some parts would not be completely functional, the best part of the MAGMA server would. Otherwise, they would not be saying this (from their website:

What is Magma?

Magma is Lavabit’s open source, commercial-grade, and full-featured server ready for use with the Dark Internet Mail Environment. Magma is now ready for commercial implementation and will fundamentally change the way business transmits encrypted data. Whether you are an individual, SME, or corporate enterprise wanting your own DIME compatible server, the Lavabit technical team can assist with your implementation and development needs.

But no; unluckily for us all, MAGMA seems far from being “full-featured server ready for use with the Dark Internet Mail Environment”. This is the first of a series about my impressions on MAGMA and the DIME standard. Keep reading!

First thing that do not seem to work: its tools.


After being able to compile and run MAGMA, I wanted to delve into the concept of “signets” and the “DIME management record”. I read the specs document, dated from 2015, and after that I tried the “signet” tool under dev/tools. This tool can generate new signets,  sign the SSR files (sort of a CSR file) and dump some information about signets. Of course, it worked out-of-the-box, at least apparently. This is me generating a new organizational signet for my MAGMA test environment:

../../signet -g
Organization name: LUD.ORG
Organization address: ADDRESS
Organization country: COUNTRY
Organization postal code: POSTAL_CODE
Organization phone number: PHONE_NUMBER

After running the previous command, I had two files: the signet itself and the private keys file:

ls -l lud*
-rw——- 1 root root 176 mai 26 23:33
-rw-r–r– 1 root root 531 mai 26 23:34

Now some basic stuff, like getting some information from this new signet:

../../signet -d
— version: 1, size = 333, signet type = organizational
— 1 Primary-Organizational-Key -> QO3pMGOqP51Wz/Q8HRgLP4U0eIhYC+29kT0fDaSyX36B

Obviously, you don’t want to have the dime.localhost.localdomain.signet in your MAGMA testing environment. You want to test your own signets. So replacing these two server configuration lines with the ones pointing to my new signet and its private keys file counterpart only seemed natural at the time:

magma.dime.key = sandbox/etc/
magma.dime.signet = sandbox/etc/

Then, I re-started the MAGMA server and the first issue arose:

Unable to parse the PRIME organizational signing key.
Unable to initialize the privacy respecting internet mail environment. Exiting.
magma.init != shutdown {23 != 39}
Magma shutdown complete.

Of course, I was puzzled. This change seemed trivial at the time. So I looked for issues in the code, using the “Unable to parse the PRIME organizational signing key” as the starting point. Soon I realized that the main problem was that the MAGMA developers do not seem to follow their own specs document so close. With the signet tool,  the POK for this new organizational signet was 44-byte long, base64-encoded:


This is so in the specs document. On the other hand, the already provided dime.localhost.localdomain.signet POK is 43-byte long:

../../signet -d dime.localhost.localdomain.signet
— version: 1, size = 139, signet type = organizational
Primary-Organizational-Key -> h44kA4AXy2gFnlF+osucG2t4SOBeu8CA3WWxo6RLfIA

WTF? Following the code path, I ended up right here:

                serial_size = ED25519_KEY_SIZE + 1;
                if (!(serial_key = malloc(serial_size))) {
                        RET_ERROR_PTR(ERR_NOMEM, "could not allocate memory for serialized signing key");
                serial_key[0] = format;
                memcpy(serial_key + 1, key->public_key, ED25519_KEY_SIZE);

So the first byte of the key, that is, serial_ley[0] is 0x40 (SIGNKEY_DEFAULT_FORMAT). This is what makes the base64-encoded key 44-byte long. The magma server routines were expecting a 43-byte base64-encoded string instead! This was not what the specs document says at all! So I made this slight alteration:

//              serial_key[0] = format;
//              memcpy(serial_key + 1, key->public_key, ED25519_KEY_SIZE);
                memcpy(serial_key, key->public_key, ED25519_KEY_SIZE);

After that, I re-built the signet tool:

make signet
Building src/providers/dime/signet/signet.c
Constructing signet

And I generated a new signet, this time I made sure its POK was 43-byte long (base64-encoded):

../../signet -d
— version: 1, size = 287, signet type = organizational
— 1 Primary-Organizational-Key -> E7gyvx3E6ksBVkg9CD5XBoXX18txj45iFSqtn9NLqjA

This time, the MAGMA server ran with no issues at all:

00:21:05 – src/engine/context/process.c – process_start() – 343] = Magma initialization complete.

Signing SSR files

Of course, this small alteration broke the signing of SSR files:

../../signet -s “” -r -k
The signet is not a valid SSR.

After going through the code once again, I ended up here:

       //switch (serial_key[0]) {
                // This not applies here anymore!
/*              if (key_size != ED25519_KEY_SIZE + 1) {
                        PUSH_ERROR(ERR_UNSPEC, "invalid signet signing key size or format");
                        key = NULL;
                //key = _deserialize_ed25519_pubkey(serial_key + 1);
                key = _deserialize_ed25519_pubkey(serial_key);
                key = NULL;
                PUSH_ERROR_FMT(ERR_UNSPEC, "unsupported format specifier for signing key: %u", serial_key[0]);
        if (!key) {
                RET_ERROR_PTR(ERR_UNSPEC, "could not convert signet serial format key to object");
        return key;

The lines commented out are mine, of course. With this yet another small alteration, and after re-bulding the signet tool, now the singing of SSR files are working and the MAGMA server runs and everything looks great …. right?

../../signet -s “” -r -k
User name: Test MAGMA
User address: ADDRESS
User country: COUNTRY
User postal code: POSTAL_CODE
User phone number: PHONE_NUMBER

ls -lt test*
-rw-r–r– 1 root root 609 mai 27 00:50
-rw-r–r– 1 root root 156 mai 27 00:24
-rw-r–r– 1 root root 271 mai 27 00:24

Not quite. More on MAGMA soon! In the meantime, if you happen to be a MAGMA developer, I emailed and I have opened a new issue on github about this, so please let me know any improvements about these issues if possible, that would be great!