DKIM - DomainKeys Identified Mail¶
Principe et fonctionnement¶
DKIM (RFC 6376) utilise la cryptographie asymétrique pour signer numériquement les emails. Cette signature garantit :
- Authenticité : L'email provient bien du domaine revendiqué
- Intégrité : Le contenu n'a pas été modifié en transit
Flux de signature DKIM¶
┌─────────────────────────────────────────────────────────────┐
│ Serveur Émetteur │
│ │
│ 1. Email créé │
│ From: sender@example.com │
│ Subject: Test │
│ Body: Hello World │
│ │
│ 2. Extraction des en-têtes à signer │
│ (From, Subject, Date, ...) │
│ │
│ 3. Calcul du hash │
│ hash = SHA256(From + Subject + Date + Body) │
│ │
│ 4. Signature avec clé privée │
│ signature = RSA_sign(hash, private_key) │
│ │
│ 5. Ajout de l'en-tête DKIM-Signature │
│ DKIM-Signature: v=1; a=rsa-sha256; d=example.com; │
│ s=selector1; h=from:subject:date; │
│ bh=<body_hash>; │
│ b=<signature> │
└─────────────────────────────────────────────────────────────┘
│
│ Email signé envoyé
▼
┌─────────────────────────────────────────────────────────────┐
│ Serveur Récepteur │
│ │
│ 1. Extraction du domaine et sélecteur de DKIM-Signature │
│ d=example.com, s=selector1 │
│ │
│ 2. Requête DNS │
│ selector1._domainkey.example.com TXT │
│ │
│ 3. Récupération de la clé publique │
│ v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4... │
│ │
│ 4. Vérification de la signature │
│ hash_recalculé = SHA256(From + Subject + Date + Body) │
│ RSA_verify(signature, hash_recalculé, public_key) │
│ │
│ 5. Résultat │
│ Pass / Fail / TempError / PermError │
└─────────────────────────────────────────────────────────────┘
Composants DKIM¶
Côté émetteur :
- Clé privée : Stockée sur le serveur mail (fichier sécurisé)
- Logiciel de signature : OpenDKIM, rspamd, dkimpy-milter
Côté DNS :
- Clé publique : Publiée dans un enregistrement TXT
- Format :
selector._domainkey.domain.com
Côté récepteur :
- Logiciel de vérification : Intégré dans la plupart des MTA modernes
En-tête DKIM-Signature¶
L'en-tête DKIM-Signature contient tous les paramètres de la signature.
Exemple complet¶
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=selector1;
t=1707566400; bh=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN/XKdLCPjaYaY=;
h=From:To:Subject:Date:Message-ID;
b=dzdVyOfAKCdLXdJOc4G2q8D0c8a8fUj/0g2O3ynPy0SV8xN
kS3Kf3BmO9hD7KlPeP0M2xD8q3K5LpN7O8Q==
Paramètres de DKIM-Signature¶
| Tag | Obligatoire | Description | Exemple |
|---|---|---|---|
v | Oui | Version DKIM | v=1 |
a | Oui | Algorithme de signature | a=rsa-sha256 |
d | Oui | Domaine signataire | d=example.com |
s | Oui | Sélecteur | s=selector1 |
b | Oui | Signature (base64) | b=dzdVyOfAK... |
bh | Oui | Hash du corps (base64) | bh=frcCV1k9o... |
h | Oui | En-têtes signés | h=from:to:subject:date |
c | Non | Canonicalisation | c=relaxed/relaxed |
t | Non | Timestamp | t=1707566400 |
x | Non | Expiration | x=1707570000 |
l | Non | Longueur du corps signée | l=1234 |
i | Non | Identité de l'agent | i=@example.com |
z | Non | Copie des en-têtes originaux | (rarement utilisé) |
Algorithmes de signature¶
Supportés :
rsa-sha256: Recommandé (RSA avec SHA-256)rsa-sha1: Déprécié (moins sécurisé)ed25519-sha256: Moderne (RFC 8463, support limité)
Taille de clé RSA :
- 1024 bits : Minimum, déprécié
- 2048 bits : Recommandé
- 4096 bits : Plus sécurisé mais plus lourd (problème avec le DNS)
Canonicalisation¶
La canonicalisation définit comment normaliser les en-têtes et le corps avant signature.
Format : c=<header>/<body>
Options :
simple: Aucune modification (strict)relaxed: Normalisation (espaces, casse, ligne vide)
Exemples :
c=simple/simple: Strict pour en-têtes et corpsc=relaxed/relaxed: Recommandé (tolère les modifications mineures)c=relaxed/simple: En-têtes flexibles, corps strict
Pourquoi relaxed ? Les serveurs intermédiaires peuvent modifier légèrement les emails :
- Ajout/suppression d'espaces
- Modification de la casse dans les en-têtes
- Ajout de lignes vides
relaxed tolère ces modifications sans invalider la signature.
En-têtes signés (tag h)¶
La liste des en-têtes inclus dans la signature.
En-têtes recommandés à signer :
En-têtes à toujours signer :
From: Obligatoire (vérifié par DMARC)SubjectDateMessage-ID
En-têtes à ne PAS signer :
Received: Ajouté par chaque serveurReturn-Path: Modifié lors du transitX-*: En-têtes personnalisés souvent modifiés
Attention : Un en-tête non signé peut être modifié sans invalider DKIM.
Enregistrement DNS DKIM¶
Format de l'enregistrement¶
Nom : <selector>._domainkey.<domain> Type : TXT Valeur : v=DKIM1; k=rsa; p=<public_key>
Exemple :
selector1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5N3lnvvrYgPCRSoqn+awTpkNkRUn7W..."
Tags de l'enregistrement DNS¶
| Tag | Description | Valeur par défaut | Exemple |
|---|---|---|---|
v | Version | DKIM1 | v=DKIM1 |
k | Type de clé | rsa | k=rsa ou k=ed25519 |
p | Clé publique (base64) | Obligatoire | p=MIGfMA0GCS... |
t | Flags | aucun | t=s (mode strict) ou t=y (mode test) |
s | Type de service | * (tous) | s=email |
h | Algorithmes de hash acceptés | tous | h=sha256 |
n | Notes | aucune | n=Notes for admins |
Flags importants¶
Flag t=y (mode test) :
Signature acceptée même si invalide (pour tests).
Flag t=s (mode strict) :
L'identité (i=) doit correspondre exactement au domaine (d=).
Révocation d'une clé DKIM¶
Pour révoquer une clé sans supprimer l'enregistrement :
La clé publique vide (p=) invalide toutes les signatures avec ce sélecteur.
Sélecteurs DKIM¶
Qu'est-ce qu'un sélecteur ?¶
Le sélecteur est un identifiant permettant de publier plusieurs clés DKIM pour un même domaine.
Avantages :
- Rotation des clés : Publier une nouvelle clé avant de révoquer l'ancienne
- Séparation des flux : Une clé par service (marketing, transactionnel, etc.)
- Multi-serveurs : Une clé par serveur d'envoi
Nommage des sélecteurs¶
Exemples courants :
default: Sélecteur par défautselector1,selector2: Numérotation202602: Date de rotation (année + mois)marketing,transactional: Par type d'emailserver1,server2: Par serveur
Recommandation : Utiliser la date pour faciliter la rotation.
Rotation des clés¶
Processus de rotation tous les 6-12 mois :
Étape 1 : Créer une nouvelle paire de clés avec un nouveau sélecteur
Étape 2 : Publier la nouvelle clé dans le DNS
Étape 3 : Attendre la propagation DNS (24-48h)
Étape 4 : Configurer le serveur pour utiliser le nouveau sélecteur
Étape 5 : Surveiller pendant 1 semaine
Étape 6 : Révoquer l'ancienne clé
Étape 7 : Après 30 jours, supprimer l'ancien enregistrement DNS
Résultats DKIM¶
| Résultat | Description | Action |
|---|---|---|
| pass | Signature valide | Accepter |
| fail | Signature invalide | Rejeter ou marquer |
| policy | Signature valide mais non conforme à la politique | Vérifier alignement DMARC |
| neutral | Signature ne peut pas être évaluée | Accepter |
| temperror | Erreur temporaire DNS | Réessayer |
| permerror | Erreur permanente (clé invalide, DNS) | Rejeter ou marquer |
| none | Pas de signature DKIM | Vérifier SPF/DMARC |
Génération des clés DKIM¶
Avec OpenDKIM¶
# Installation
sudo apt install opendkim-tools # Debian/Ubuntu
sudo dnf install opendkim-tools # RHEL/Rocky
# Génération de la paire de clés
opendkim-genkey -b 2048 -d example.com -s selector1
# Fichiers créés :
# - selector1.private : clé privée (à protéger)
# - selector1.txt : clé publique (pour le DNS)
Contenu de selector1.txt :
selector1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5N3lnvvrYgPCRSoqn+awTpkNkRUn7W..."
Avec OpenSSL¶
# Génération de la clé privée
openssl genrsa -out private.key 2048
# Extraction de la clé publique
openssl rsa -in private.key -pubout -out public.key
# Conversion en format DKIM (retirer les lignes BEGIN/END et les retours à la ligne)
grep -v "BEGIN\|END" public.key | tr -d '\n'
Sécurisation de la clé privée¶
# Déplacer la clé dans un répertoire sécurisé
sudo mkdir -p /etc/opendkim/keys/example.com
sudo mv selector1.private /etc/opendkim/keys/example.com/
# Permissions restrictives
sudo chown opendkim:opendkim /etc/opendkim/keys/example.com/selector1.private
sudo chmod 600 /etc/opendkim/keys/example.com/selector1.private
# Vérification
ls -l /etc/opendkim/keys/example.com/selector1.private
# Résultat attendu : -rw------- 1 opendkim opendkim
Problèmes courants DKIM¶
Clé publique trop longue¶
Problème : Les clés RSA 4096 bits dépassent la limite DNS (255 caractères par chaîne).
Solution : Découper en plusieurs chaînes :
selector1._domainkey.example.com. IN TXT (
"v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
" ...suite de la clé..."
)
Ou utiliser RSA 2048 bits (recommandé).
Signature invalide après modification du message¶
Causes :
- Serveur intermédiaire modifie le corps (ajout de disclaimer, antivirus)
- Liste de diffusion ajoute un footer
- Changement d'encoding (quoted-printable, base64)
Solution : Utiliser c=relaxed/relaxed.
En-tête From non signé¶
Problème : DMARC échoue si l'en-tête From n'est pas dans le tag h.
Vérification :
Solution : S'assurer que from est toujours dans la liste h.
Erreur de requête DNS¶
Symptôme : temperror ou permerror
Causes :
- Enregistrement DNS absent ou mal formé
- DNSSEC invalide
- Serveur DNS injoignable
Vérification :
Multiple signatures DKIM¶
Un email peut avoir plusieurs signatures DKIM (multi-domaines, services tiers).
Exemple :
DKIM-Signature: v=1; d=example.com; s=selector1; ...
DKIM-Signature: v=1; d=mailchimp.com; s=k1; ...
DMARC : Seule la signature alignée avec le domaine From compte.
DKIM et listes de diffusion¶
Les listes de diffusion posent problème pour DKIM :
- Modification du sujet :
[Liste] Sujet original - Ajout de footer : "Unsubscribe: http://..."
- Changement du From :
sender@example.com→sender@example.com via list@mailing.org
Conséquence : Signature DKIM invalide.
Solutions :
- ARC (Authenticated Received Chain) : Préserve les résultats d'authentification
- DKIM replay : La liste re-signe l'email avec son propre domaine
c=relaxed/relaxed: Tolère certaines modifications
DKIM pour sous-domaines¶
Les sous-domaines doivent avoir leurs propres clés DKIM.
Exemple :
# Domaine principal
selector1._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCS..."
# Sous-domaine
selector1._domainkey.mail.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgk..."
Politique : Il n'y a pas d'héritage des clés DKIM.
Avantages et limites de DKIM¶
Avantages¶
- Garantit l'intégrité du contenu
- Résiste au transfert d'emails (contrairement à SPF)
- Permet la signature par des services tiers
- Clés révocables et rotables
Limites¶
- Complexité de mise en place (gestion des clés)
- Vulnérable aux modifications du corps (si
c=simple) - Ne garantit pas que le domaine
d=correspond auFromvisible (rôle de DMARC) - Taille des clés peut poser problème avec DNS
Vérification DKIM¶
En ligne¶
- DKIMValidator : https://dkimvalidator.com/
- Mail-Tester : https://www.mail-tester.com/
- MXToolbox DKIM : https://mxtoolbox.com/dkim.aspx
En ligne de commande¶
# Vérifier l'enregistrement DNS
dig selector1._domainkey.example.com TXT +short
# Tester la signature d'un email
python3 -c "import dkim; print(dkim.verify(open('email.eml', 'rb').read()))"
Analyser les en-têtes reçus¶
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=selector1 header.b=dzdVyOfA
DKIM et services tiers¶
Mailchimp¶
Mailchimp signe automatiquement les emails avec sa propre clé :
Pour utiliser votre domaine :
- Générer une clé DKIM dans Mailchimp
- Publier la clé dans votre DNS
- Vérifier dans Mailchimp
SendGrid¶
Démarche similaire avec authentification du domaine.
Office 365¶
DKIM activable dans le portail admin avec génération automatique des clés.
Récapitulatif DKIM¶
Forces :
- Signature cryptographique robuste
- Garantit l'intégrité
- Fonctionne avec le transfert d'emails
- Permet la rotation des clés
Faiblesses :
- Complexité technique
- Gestion des clés privées
- Vulnérable aux modifications du corps (selon canonicalisation)
- Ne lie pas le domaine signataire au
Fromvisible
Bonnes pratiques :
- Utiliser RSA 2048 bits
- Algorithme
rsa-sha256 - Canonicalisation
relaxed/relaxed - Toujours signer l'en-tête
From - Rotation des clés tous les 6-12 mois
- Protéger les clés privées (chmod 600)
- Utiliser un sélecteur basé sur la date
- Publier la nouvelle clé avant de révoquer l'ancienne