How to use DKIM with Ed25519

The original DKIM specification only allowed RSA signatures. Although there is nothing wrong with RSA, the keys are unfortunately rather large, which causes issues in setting up the DKIM DNS records. The DKIM specification also did not require DKIM validators to support keys larger than 2048 bits, so cryptographic strength is limited.

With the introduction of RFC8463 it has become possible to use DKIM with the Edwards-curve Digital Signature Algorithm (EdDSA). EdDSA is a type of elliptic curve cryptography (ECC) that uses the Curve25519 elliptic curve. Hence, this type of cryptographic signature is commonly referred to as Ed25519.

Compared to a 2048-bit RSA key, Ed25519 has the benefit of having much smaller keys but higher cryptographic strength. This allows for higher strength signatures, without hitting length limitations in DNS records.

In this article we'll explore how to create an Ed25519 key pair using OpenSSL, and how to create an Ed25519 DKIM DNS record from that key pair.

Who is this article for?

This article is intended for email administrators and developers who want to sign their email with Ed25519 DKIM signatures. We expect that you are already familiar with setting up DKIM signing with RSA.

To verify that your software supports Ed25519 signatures and for implementation details, please refer to the documentation of your MTA or DKIM signing software.

Note that if you use a cloud based email service that supports Ed25519 signing, your cloud email provider should supply the DNS records to set.

A word of caution

Please be aware that Ed25519 DKIM support is currently very limited amongst most email services. Most DKIM signing software does not yet support signing with Ed25519 signatures, and most verifiers (receivers) cannot verify Ed25519 signatures yet.

Never rely on Ed25519 DKIM signatures exclusively. Email signed with Ed25519 DKIM signatures should always include a fallback RSA DKIM signature.

Generating the key pair

To start, we create a new Ed25519 private key using OpenSSL. Note that unlike RSA, with Ed25519 there are no options such as key length to choose from. An Ed25519 key always has a fixed size of 256 bits.

openssl genpkey -algorithm ed25519 -out dkim_private.pem

We then use OpenSSL again to calculate the public key from the newly created private key.

openssl pkey -in dkim_private.pem -pubout -out dkim_public.pem

The resulting public key will look something like this:

-----END PUBLIC KEY-----

Notice that the Ed25519 keys are much smaller than a 2048-bit RSA public key that would normally be used for DKIM. An Ed25519 key is only 256 bits in size, yet its cryptographic strength is comparable to a 4096-bit RSA key.

Creating the DNS record

A DKIM TXT resource record with Ed25519 keys differs from the regular RSA DKIM record as follows:

With RSA, the p value of the DKIM DNS record is expected to contain an ASN.1 structure with the RSA public key. This is needed because RSA keys can have various properties such as the key size and the exponent.

With Ed25519 there are no settings, so there is no need for an ASN.1 structure. When using Ed25519 the p value in the DKIM DNS record must only contain the BASE64 encoded public key, without an ASN.1 structure. This makes the record even smaller. So small in fact, that the entire DKIM record can now fit in a single 255 byte DNS <character-string> structure, which makes fetching the DKIM record a lot more efficient for validators.

This does mean that we need to do a little more work on the command line, as OpenSSL unfortunately does not have an option to output the raw key, it is always wrapped in an ASN.1 structure.

Using the OpenSSL asn1parse function, we can extract the raw Ed25519 key from the ASN.1 structure in the PEM encoded public key file, and then convert it back to BASE64 format:

openssl asn1parse -in dkim_public.pem -offset 12 -noout -out /dev/stdout | openssl base64

Note for Windows users

When using OpenSSL native under Windows (either in the command prompt, or PowerShell), the OpenSSL piping behavior is problematic, as there is no /dev/stdout available on Windows environments. As a workaround, first write the raw key data to an intermediate file pubkey.asn1, then load it into the BASE64 encoder from file.

openssl asn1parse -in dkim_public.pem -offset 12 -noout -out pubkey.asn1

openssl base64 -in pubkey.asn1

The output of this command will be the p value of your DKIM DNS record. Notice how this value is shorter than the value in dkim_public.pem generated by OpenSSL, this is because the ASN.1 structure is stripped.

Now we can create our Ed25519 elliptic curve DKIM record. For the public key example earlier in this article, the resulting DKIM record would look like this:

v=DKIM1; k=ed25519; p=7x8OfAKmZwqS4ZoWsIozL+2rRvm9DYN1dqdxQGybKuU=

Now we can immediately see the main benefit of Ed25519 with DKIM: even with the optional whitespace and optional v=DKIM1 part (yes, it is optional), this record is only 67 characters long, which makes it fit inside a single DNS <character-string> object with plenty room to spare.

Once you have published the DNS record, you can use the Mailhardener DKIM record validator to validate and inspect the DNS record.

Transition period considerations

As with any new standard in email, it is expected that it will take some time before Ed25519 validation is a common feature in email validators (the receiving services). As such, it is not recommended to exclusively rely on Ed25519 for DKIM.

The signer (sending email service) should use a dual DKIM signature approach where email is signed with both an Ed25519 signature, and an RSA signature for backwards compatibility.

This means that 2 DKIM DNS records must be created. One containing the Ed25519 key, and one with a fall-back RSA type key. The two DKIM DNS records must use a different selector, as DKIM does not allow multiple DKIM records to exist with the same selector.

The signer (the sending email service) must now add two DKIM-signature headers to the email: one with a=rsa-sha*, and one with a=ed25519-sha256. The d and i (if set) values in both DKIM signature header must be equal between both signatures.

A properly implemented validator should prefer the signature with ed25519-sha256 algorithm over the rsa-sha* algorithm if supported. The validator should not validate the rsa-sha* signature if a valid ed25519-sha256 is found for the same d and i value.

Legacy validator services that do not support ed25519-sha256 should ignore that DKIM-signature and fall back to the rsa-sha* signature.

Note: with RSA DKIM signatures the SHA1 hashing algorithm could be used. SHA1 has been proven unsafe and should no longer be used. When using ed25519 signatures, only SHA256 is allowed to be used, thus the only allowed value for a in the DKIM header is ed25519-sha256.

Closing thoughts

Ed25519 DKIM signatures offer a number of benefits for both signers and validators.

Unfortunately, we can't rely exclusively on Ed25519 DKIM signatures as there will always be legacy validators that do not support Ed25519. However, with double-signing email with Ed25519 and RSA you can already benefit from the higher cryptographic strength of Ed25519 DKIM signatures and also help accelerate the adoption of Ed25519 for DKIM.

Further reading

See also

Share your thoughts!

On last thing: If you have questions, comments or thoughts on this article, don't hesitate to shoot us an email.

You can also follow and reach us on Twitter @Mailhardener.

With Mailhardener you can configure, validate and monitor your domain for all aspects of email security. Mailhardener is free to use for a single domain.
Sign up now