Halon Engage and Halon Protect now include experimental DKIM2 support through a new open-source extras module, giving operators a way to sign, verify, and observe the next generation of email authentication on real mail flows.
The IETF specification for DKIM2 is still a draft, not a final RFC, and our implementation reflects that. Coverage is incomplete, and the details will change as the working group progresses. We do not recommend using DKIM2 results to accept, reject, or quarantine production mail today. We do recommend running it alongside your existing DKIM and DMARC checks: sign and verify in both ways, log the outcomes, provide feedback to the community, and build operational experience while the standard matures.
That is the point of shipping early. Halon has a long track record of implementing email standards ahead of the curve, most recently with RFC 9989 in Halon Protect 26.2. DKIM2 is earlier in its lifecycle, but the same principle applies. Standards improve when infrastructure vendors and operators can try them on production traffic and feed that experience back into the community.
If you are new to DKIM2, we have published separate guides for senders and mailbox providers that explain what the new standard is looking to solve. This post focuses on what Halon adds and how to use it.
DKIM2 introduces new headers (Message-Instance and DKIM2-Signature) and new verification semantics. In Halon, signing and verification are provided by the open-source dkim2 extras module, which exports two HSL functions imported from extras://dkim2:
dkim2_sign() generates the Message-Instance and DKIM2-Signature headers for a message. It takes the mail file, envelope sender and recipients, DNS selector and signing domain, and a PEM-encoded private key (PKCS#8 Ed25519/RSA or PKCS#1 RSA). On success, it returns the complete header fields ready to prepend to the message.dkim2_verify() validates the newest DKIM2-Signature on ingress. Like signing, it requires envelope data (mailfrom and rcptto) because DKIM2 binds more transmission context to the signature.This sits alongside the built-in DKIM functions (signDKIM, verifyDKIM), which are unchanged. You can run both stacks on the same message without affecting current signing or verification behavior.
Install the module from the Halon package repository:
apt-get install halon-extras-dkim2
A typical sign-on-exit looks like this:
import { dkim2_sign } from "extras://dkim2";
import $privatekey from "file://dkim2_ed25519.key";
$mail = $arguments["mail"];
$sender = $transaction["sender"];
$recipients = array_map(function ($x) { return $x["recipient"]; },
$transaction["recipients"]);
$selector = "ed25519";
$signing_domain = "example.com";
$dkim2options = [];
$signed = dkim2_sign(
$mail->toFile(),
$sender,
$recipients,
$selector,
$signing_domain,
$privatekey,
$dkim2options
);
if (!$signed["result"])
throw Error("dkim2 signature signing error: " . $signed["error"]);
foreach ($signed["headers"] as $header)
$mail->modifyContent(0, 0, $header);
import { dkim2_verify } from "extras://dkim2";
$mail = $arguments["mail"];
$sender = $transaction["sender"];
$recipients = array_map(function ($x) { return $x["recipient"]; },
$transaction["recipients"]);
$dkim2options = [
"ignoretimestamp" => true,
];
$verified = dkim2_verify(
$mail->toFile(), $sender, $recipients, $dkim2options
);
if (!$verified["result"])
echo "dkim2 signature not found";
else if ($verified["result"] != "pass")
echo "dkim2 signature verification error: " . $verified["error"];
else
echo "dkim2 verified ok!";
dkim2_sign returns result, error, and headers. dkim2_verify returns result and error, with result set to pass, permerror, or temperror. Use these for logging and comparison against your existing DKIM outcomes.
For now, DKIM2 should run alongside DKIM, rather than replace it. During the transition, operators should expect to encounter both on the same message, and Halon is built for that.
On the signing side, you can add DKIM2 signatures to outbound mail while continuing to DKIM-sign as you do today. On the receiving side, you can verify both independently and compare the results.
This release covers the core signing and verification workflows operators need to start experimenting with: originator sign-on-exit, receiver verify-on-ingress, and forwarder verify-then-sign.
Several areas of the draft specification are not yet implemented. Verification handles the newest DKIM2-Signature but does not unwind a full inter-hop chain. Automated Reviser recipes are out of scope; manual modification steps can be supplied when signing, but Halon does not generate them. DSN signing and Halon Classify integration are also not included.
These gaps are deliberate for now. As the IETF draft stabilizes and we learn from operator feedback, we will extend the implementation.
Experimental DKIM2 support is available as the halon-extras-dkim2 package through the normal Halon software repository for Halon Engage and Halon Protect. If you would like help wiring up dual-stack signing or verification, setting up logging without changing delivery policy, or understanding how this fits alongside your existing DKIM and DMARC configuration, reach out to your Halon representative or request a demo.