How to Discover All DKIM Selectors for a Domain Without Prior Knowledge


2 views

When implementing email verification systems, developers often need to verify if a domain has properly configured DKIM records. The standard DKIM verification process requires knowing the specific selector used in the email's DKIM-Signature header. However, what if you need to check a domain's DKIM setup without having any prior knowledge of its selectors?

DKIM records follow the format: {selector}._domainkey.{domain}. For example:

google._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
default._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."

Each selector represents a separate key that might be used for different purposes or services.

While there's no standardized way to enumerate all selectors for a domain, here are practical approaches:

1. Common Selector Brute-forcing

Many domains use common selector names. This Python script checks known common selectors:

import dns.resolver

COMMON_SELECTORS = ['default', 'dkim', 'domainkey', 'google', 'selector1', 
                   'selector2', 's1', 's2', 'email', 'mail', 'e1']

def check_dkim_selectors(domain):
    results = {}
    for selector in COMMON_SELECTORS:
        try:
            query = f"{selector}._domainkey.{domain}"
            answers = dns.resolver.resolve(query, 'TXT')
            records = [r.to_text() for r in answers]
            results[selector] = records
        except dns.resolver.NXDOMAIN:
            continue
        except dns.resolver.NoAnswer:
            continue
    return results

2. DNS Zone Walking

If you have access to the domain's DNS server that supports zone transfers (AXFR), you could potentially list all records. However, this is rarely possible for external domains due to security restrictions.

3. Using Certificate Transparency Logs

Some domains include DKIM selectors in their SSL certificates. You can search CT logs for potential selectors:

import requests

def find_selectors_in_ct(domain):
    url = f"https://crt.sh/?q=%.{domain}&output=json"
    response = requests.get(url)
    if response.status_code == 200:
        certificates = response.json()
        selectors = set()
        for cert in certificates:
            if '_domainkey' in cert['name_value']:
                selector = cert['name_value'].split('._domainkey')[0]
                selectors.add(selector)
        return list(selectors)
    return []
  • There's no guaranteed way to discover all selectors as they're chosen by domain administrators
  • The absence of common selectors doesn't necessarily mean DKIM isn't configured
  • Some domains rotate selectors periodically for security reasons
  • Enterprise domains often use unique, non-obvious selector names

If your goal is simply to verify that a domain cares about email security, consider these alternatives:

  1. Check for DMARC records at _dmarc.{domain}
  2. Verify SPF records
  3. Look for MTA-STS policies

DKIM (DomainKeys Identified Mail) validation relies on DNS lookups using specific selector-based subdomains. A standard DKIM record follows the pattern {selector}._domainkey.{domain}, where the selector is arbitrary (e.g., 'default', 'dkim', 's1').

But here's the challenge: When you want to verify if a domain has any DKIM setup without knowing the selectors in advance, there's no direct DNS query to list all possible selectors. Unlike SPF records (which have a single standard TXT record at the domain root), DKIM selectors are decentralized by design.

While there's no perfect solution, here are practical approaches:

1. Common Selector Brute-Forcing

Check known/common selector patterns programmatically:

import dns.resolver

def check_common_selectors(domain):
    common_selectors = [
        'default', 'dkim', 'domainkey', 's1', 'selector1',
        'google', 'mandrill', 'sendgrid', 'amazonses'
    ]
    valid_records = []
    
    for selector in common_selectors:
        try:
            query = f"{selector}._domainkey.{domain}"
            answers = dns.resolver.resolve(query, 'TXT')
            for rdata in answers:
                if "v=DKIM1" in str(rdata):
                    valid_records.append((selector, str(rdata)))
        except dns.resolver.NXDOMAIN:
            continue
    
    return valid_records

2. DNS Zone Walking (When Possible)

If you have access to the domain's DNS server that allows zone transfers (AXFR), you can:

dig axfr example.com | grep "_domainkey"

Note: Most public DNS servers block zone transfers for security reasons.

3. Certificate Transparency Logs

Some domains expose DKIM selectors through SSL certificates. Tools like crt.sh can help discover subdomains that might contain DKIM records.

Let's verify one of Google's known selectors:

dig google._domainkey.gmail.com TXT +short
"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Kd87/U7..."

For organizations needing comprehensive DKIM verification:

  • Commercial email security platforms often maintain selector databases
  • DMARC reports may reveal valid selectors in use
  • Historical email analysis can extract past used selectors

Remember that:

  • False negatives are possible (undiscoverable selectors)
  • Domains may have valid DKIM but not use it for all emails
  • Selector discovery shouldn't replace proper email authentication checks