CAI Technology
Menu ☰
aegis · · 8 min read

DKIM: Proper Email Signing and Key Rotation Every 6-12 Months

DKIM cryptographically authenticates your emails. Use 2048-bit RSA or Ed25519, multiple selectors, and periodic rotation to limit damage in case of compromise.

CAI Technology · Last reviewed: 5/9/2026
DKIM: Proper Email Signing and Key Rotation Every 6-12 Months

In Short

DKIM (DomainKeys Identified Mail, RFC 6376) adds a cryptographic signature to every outgoing email, signed with a private key held by your MTA. The public key is published in DNS under a selector. The receiver (Gmail, Outlook365) verifies the signature and — if valid and matching the domain in From: — confirms that the email was not modified in transit and originates from an authorized entity.

In 2026, DKIM is a de facto requirement: Gmail and Yahoo have mandated since February 2024 that all bulk senders (>5000 messages/day to their accounts) must have functional SPF + DKIM + DMARC — otherwise emails are rejected or flagged as spam. For any company with newsletters, automated invoices, or transactional notifications, correct DKIM is the difference between 95%+ deliverability and 60%.

The often ignored aspect: the DKIM key is not set-and-forget. Like any cryptographic key, it must be rotated periodically. A compromised key (hacked server, exposed backup, former employee with access) allows an attacker to sign legitimate emails on your behalf for months until you notice.

Concrete Attacks Prevented

Scenario 1 — Content Tampering in Transit

An on-path attacker (ISP network, datacenter) intercepts an email with an attached PDF invoice. They modify the IBAN in the PDF before the email reaches the client. Without DKIM, the modification is undetectable. With DKIM (signature on Subject:, From:, Date: and body hash), any modification invalidates the signature — the receiver rejects or marks it as suspicious.

Scenario 2 — Replay with Altered Content (DKIM Key Compromise)

A company’s 1024-bit DKIM key was cracked in 2012 (public Zachary Harris case). The attacker sent a validly signed email to Google, claiming to be the company CEO. 1024-bit RSA keys are technically breakable with moderate cloud resources (~$75,000 USD in 2025) — a minimum of 2048-bit is mandatory.

Scenario 3 — Former Employee with Private Key Access

The DevOps engineer fired in 2024 copied /etc/postfix/dkim/private.key before leaving. For 8 months, until the new team rotated the key (after reading this article), the former employee could have signed valid emails to any recipient — impersonating the CEO, accounting, etc. Mandatory rotation every 6-12 months limits this window.

Business Impact

Aspect1024-bit Key, No Rotation2048-bit Key + 6-Month Rotation
Cost to compromise key (2026)~$75,000 USD (factorization)>10^60 years (computationally infeasible)
Compromise window post-leakinfinitemax 6 months
Gmail/Yahoo bulk deliverabilityrejected (since 2024)accepted
DORA / NIS2 Auditfindingcovered
Periodic rotation cost~1h/operation, 2x/year

Implementation — Step-by-Step Guide

Step 1 — Generate 2048-bit DKIM Key (or Ed25519)

For OpenDKIM / Postfix:

# RSA 2048-bit (universally compatible)
opendkim-genkey -b 2048 -d firma.ro -s 2026a -v

# Or Ed25519 (modern, fast, majority supported since 2024)
opendkim-genkey -t ed25519 -d firma.ro -s 2026a-ed -v

Output: two files — 2026a.private (keep only on MTA, mode 0600, root) and 2026a.txt (DNS TXT record).

Do not use 1024-bit. RFC 8301 explicitly marks 1024 as weak. For retro-compatibility with old MTAs that do not support Ed25519, publish both selectors (RSA 2048 + Ed25519) — the receiver chooses.

Step 2 — Publish Public Key in DNS

2026a._domainkey.firma.ro.  IN  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCA..."

Watch out for TXT record length — over 255 characters must be split into segments; most DNS providers handle this automatically if you enter it on a single line in the UI.

Verification:

dig +short TXT 2026a._domainkey.firma.ro
opendkim-testkey -d firma.ro -s 2026a -k /etc/opendkim/keys/firma.ro/2026a.private -vvv

Step 3 — Configure MTA to Sign with New Selector

Postfix + OpenDKIM (/etc/opendkim/key.table):

2026a._domainkey.firma.ro firma.ro:2026a:/etc/opendkim/keys/firma.ro/2026a.private

Reload OpenDKIM. Send a test email to check-auth@verifier.port25.com — the automated response confirms a valid signature.

Step 4 — Rotation Procedure (Every 6-12 Months)

Rotation is performed without downtime via selector overlap:

  1. T-30 days: generate new selector (2026b), publish TXT, but do not activate signing yet.
  2. T-0: switch MTA to sign with 2026b. Leave 2026a in DNS.
  3. T+7 days: if no issues, delete 2026a from DNS (implicit revoke).
  4. T+8 days: delete private key 2026a.private from MTA + backups.

Never delete the old key immediately after rotation — emails signed before the switch are still in transit; receivers may attempt verification later.

Step 5 — Automation + Monitoring

Add an alert (cron or Zabbix) that warns you at 5.5 months from generation:

# Check key creation date and warn at 5.5 months
find /etc/opendkim/keys/ -name "*.private" -mtime +165 -exec echo "ROTATION REQUIRED: {}" \;

Log issued DKIM signatures (Postfix header_checks or Graylog) — during an audit, this demonstrates that signing was active continuously.

Common Confusions

“The default selector default is sufficient.” — Dangerous. During rotation you cannot perform overlap; you are forced to accept downtime or use only 1 permanent key (anti-pattern). Use dataframe-style selectors: 2026a, 2026b, etc.

“Ed25519 is not universally supported.” — This was true in 2018. Since 2024, Gmail, Outlook365, Yahoo, and ProtonMail all verify Ed25519. Only a few legacy on-prem MTAs do not — for those, keep RSA in parallel.

“DKIM prevents forwarding.” — Partially true. Forwarding with modification (mailing list adding a footer) breaks the signature. Solution: ARC (Authenticated Received Chain, RFC 8617) or re-DKIM at the mailing list. Clean forwarding (server-side, without rewrite) keeps the signature intact.

“Private key in Git is ok if the repo is private.” — Absolutely not. Compromised Git repo = compromised key for months. The private key lives only on the MTA, generated with umask 077, without unencrypted backups.

Check Now

ARTEMIS automatically checks: DKIM presence, key size (warning <2048-bit), alignment with DMARC, detectable expiration, and 30+ other email-security checks.


🔗 Complementary CAI Technology Solutions


Questions? tehnic@caitech.ro


We start with a 30-minute conversation.

Free AI-readiness audit for companies with 50+ employees. We reply within 24 hours.