प्रमाणन और डिलीवरबिलिटी के लिए DKIM के साथ ईमेल पर हस्ताक्षर करना

DKIM (DomainKeys Identified Mail, RFC 6376) डोमेन मालिक को आउटगोइंग ईमेल पर एक क्रिप्टोग्राफ़िक हस्ताक्षर जोड़ने की अनुमति देता है। प्राप्त करने वाले सर्वर DNS से मेल खाने वाली सार्वजनिक कुंजी लाते हैं, हैश फिर से गणना करते हैं, और एक साथ दो चीज़ें पुष्ट करते हैं: संदेश का शरीर ट्रांसिट में बदला नहीं गया, और संदेश वास्तव में डोमेन द्वारा अधिकृत प्रेषक से आया। बिना DKIM के, आधुनिक प्रदाता (Gmail, Microsoft 365, Yahoo) मेल को स्पैम के रूप में चिह्नित करते हैं, चुपचाप हटाते हैं, या डिलीवरी अस्वीकार करते हैं — उत्पादन मेल के लिए DKIM अब वैकल्पिक नहीं है।

यह मार्गदर्शिका पूरी तरह से कवर करती है Aspose.Emailके .NET के लिए DKIM नेमस्पेस। इस लेख में प्रत्येक कोड ब्लॉक इस पुस्तकालय में मौजूद चलाने योग्य उदाहरण से लिया गया है DKIMExamples प्रोजेक्ट और अंत‑से‑अंत सत्यापित किया गया है पुस्तकालय के विरुद्ध।

पूर्वापेक्षाएँ

DKIM प्रकार यहाँ स्थित हैं Aspose.Email.DKIM Namespace और केवल .NET Framework 4.0/4.5 लाइब्रेरी के बिल्ड्स के साथ वितरित करता है। इन्हें इरादतन .NET Standard 2.0 और .NET 6/8 पैकेजों से बाहर रखा गया है। नीचे दिए गए उदाहरणों का पालन करने के लिए, आपके प्रोजेक्ट को Aspose.Email असेंबली के उस संस्करण का संदर्भ देना होगा जो net45 (लक्षित net48 उपयोगकर्ता में .csproj).

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net48</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Aspose.Email">
      <HintPath>..\path\to\net45\Aspose.Email.dll</HintPath>
    </Reference>
  </ItemGroup>
</Project>

आपको एक RSA कुंजी जोड़ी की भी आवश्यकता है। निजी कुंजी आपके अनुप्रयोग में रखी जाती है और साइन करने के लिए उपयोग होती है; सार्वजनिक कुंजी DNS TXT रिकॉर्ड के रूप में प्रकाशित की जाती है ताकि प्राप्तकर्ता सत्यापित कर सकें। आज का मानक 2048-बिट कुंजी है:

openssl genrsa -out sample-private-key.pem 2048

Aspose की PemReader PKCS#1 दोनों को स्वीकार करता है (-----BEGIN RSA PRIVATE KEY-----) और PKCS#8 (-----BEGIN PRIVATE KEY-----) फ़ॉर्मेटेड फ़ाइलें।

| क्लास | भूमिका | |——-|——| | DKIMSignatureInfo | हस्ताक्षर का विवरण देता है: चयनकर्ता, डोमेन, हैश एल्गोरिद्म, कैनोनिकलाइजेशन, और कौन से हेडर कवर करने हैं। | | PemReader | RSA निजी कुंजी को PEM-फॉर्मेटेड फ़ाइल या स्ट्रीम से एक RSACryptoServiceProvider. | | MailMessage.DKIMSign(rsa, info) | एक्सटेंशन/इंस्टेंस मेथड जो संदेश की एक साइन की हुई कॉपी लौटाता है जिसमें DKIM-Signature हेडर भरा गया। | | DkimVerifier | एक साइन किए गए संदेश की DNS-आधारित सत्यापन करता है — फ़ाइल, स्ट्रीम, सिंक, या असिंक्रोनस। |

पूरी प्रक्रिया हमेशा इस प्रकार है: कुंजी लोड करें → हस्ताक्षर का विवरण दें → संदेश बनाएं → साइन करें → (वैकल्पिक) सत्यापन करें

न्यूनतम साइनिंग उदाहरण

यह सबसे छोटा कोड है जो एक वैध DKIM-हस्ताक्षरित संदेश उत्पन्न करता है:

// Load private key from PEM file
var rsa = PemReader.GetPrivateKey(PrivateKeyPath);

// Create DKIM signature information
var signInfo = new DKIMSignatureInfo("dkim", "example.com")
{
    // Default: Relaxed/Relaxed canonicalization
    // Default: RSASha1 hash algorithm
};

// Add headers to sign
signInfo.Headers.Add("From");
signInfo.Headers.Add("To");
signInfo.Headers.Add("Subject");

// Create a test email
var mailMessage = new MailMessage(
    "sender@example.com",
    "recipient@example.com",
    "Test Subject",
    "This is a test email body signed with DKIM.")
{
    From = new MailAddress("sender@example.com", "Sender Name")
};

// Sign the message
var signedMsg = mailMessage.DKIMSign(rsa, signInfo);

// Save the signed message
string outputPath = Path.Combine(DataDir, "basic-signed.eml");
signedMsg.Save(outputPath);

Console.WriteLine($"DKIM-Signature header: {signedMsg.Headers["DKIM-Signature"]?.Substring(0, 50)}...");

दो तर्कों के लिए DKIMSignatureInfo"dkim" और "example.com" — ये सेलेक्टर और डोमेन हैं। मिलकर वे प्राप्तकर्ताओं को बताते हैं कि आपका सार्वजनिक कुंजी कहाँ देखना है: DNS TXT रिकॉर्ड पर dkim._domainkey.example.com. एक छोटा चयनकर्ता नाम चुनें (आमतौर पर default, mail, या कोई तिथि जैसे 2026jan); चयनकर्ता आपको पुराना कुंजी छोड़े बिना कुंजियों को घुमाने की अनुमति देता है।

एक महत्वपूर्ण विवरण: DKIMSign एक नई वापसी करता है MailMessage इंस्टेंस के साथ DKIM-Signature हेडर जोड़ा गया। मूल संदेश अपरिवर्तित है। लौटाए गए ऑब्जेक्ट को सहेजें या भेजें, इनपुट को नहीं।

कौन से हेडर साइन करने हैं चुनना

हेडर सूचीबद्ध हैं signInfo.Headers वे ही एकमात्र हैं जिनके मान हस्ताक्षर से बंधे होते हैं. सूची में न दी गई कोई भी चीज़ रिले द्वारा संशोधित की जा सकती है बिना हस्ताक्षर को तोड़े, जो कभी‑कभी वांछनीय होता है (जैसे Received: हेडर नीचे की ओर जोड़े जाते हैं) और कभी‑कभी ख़तरनाक (जैसे छोड़ देना From अनसाइन्ड के कारण हस्ताक्षर अर्थहीन हो जाता है).

सामान्य नियम: हमेशा साइन करें From, To, Subject, Date. From विशेष रूप से DMARC संरेखण के लिए अनिवार्य है.

var signInfo = new DKIMSignatureInfo("dkim2", "example.com")
{
    Headers =
    {
        "From",
        "To",
        "Subject",
        "Date",
        "MIME-Version"
    }
};

// Create email with additional headers
var mailMessage = new MailMessage(
    "sender@example.com",
    "recipient@example.com",
    "Custom Headers Test",
    "This message includes custom headers in the DKIM signature.")
{
    From = new MailAddress("sender@example.com", "Sender"),
    Date = DateTime.UtcNow
};

// Ensure headers listed in DKIM signature are present on the message
mailMessage.Headers.Add("MIME-Version", "1.0");
mailMessage.Headers.Add("X-Custom-Header", "CustomValue");

// Sign with custom headers
var signedMsg = mailMessage.DKIMSign(rsa, signInfo);

string outputPath = Path.Combine(DataDir, "custom-headers-signed.eml");
signedMsg.Save(outputPath);

यदि आप सूची बनाते हैं Date पर लेकिन कभी सेट न करें mailMessage.Date, DKIMSign फ़ेंक्स The following headers to be signed do not exist: Date. पहले हेडर भरें, फिर साइन करें.

हैश एल्गोरिद्म — RSA‑SHA1 बनाम RSA‑SHA256

DKIM दो साइनिंग एल्गोरिद्म का समर्थन करता है. Aspose.Email में डिफ़ॉल्ट है RSASha1 पीछे की संगतता के लिए, पर हर नई परिनियोज़न को उपयोग करना चाहिए RSASha256. कई प्रदाता अब SHA-1 हस्ताक्षरों को अमान्य मानते हैं, भले ही वे क्रिप्टोग्राफ़िक रूप से सत्यापित हों.

// Example with RSASha1 (older, less secure but widely supported)
var signInfoSha1 = new DKIMSignatureInfo("dkim-sha1", "example.com")
{
    HashAlgorithm = DKIMHashAlgorithm.RSASha1,
    Headers = { "From", "To", "Subject" }
};

var mailMessage1 = new MailMessage(
    "sender@example.com",
    "recipient@example.com",
    "SHA1 Test",
    "Signed with RSASha1 algorithm.");

mailMessage1.From = new MailAddress("sender@example.com");
var signedMsgSha1 = mailMessage1.DKIMSign(rsa, signInfoSha1);

string pathSha1 = Path.Combine(DataDir, "sha1-signed.eml");
signedMsgSha1.Save(pathSha1);

// Example with RSASha256 (newer, more secure)
var signInfoSha256 = new DKIMSignatureInfo("dkim-sha256", "example.com")
{
    HashAlgorithm = DKIMHashAlgorithm.RSASha256,
    Headers = { "From", "To", "Subject" }
};

var mailMessage2 = new MailMessage(
    "sender@example.com",
    "recipient@example.com",
    "SHA256 Test",
    "Signed with RSASha256 algorithm.");

mailMessage2.From = new MailAddress("sender@example.com");
var signedMsgSha256 = mailMessage2.DKIMSign(rsa, signInfoSha256);

string pathSha256 = Path.Combine(DataDir, "sha256-signed.eml");
signedMsgSha256.Save(pathSha256);

परिणामस्वरूप DKIM-Signature हेडर एल्गोरिद्म को ट्याग के माध्यम से विज्ञापित करता है a= टैग (a=rsa-sha1 वर्सेज a=rsa-sha256). प्राप्तकर्ता इस टैग को देख कर यह तय करते हैं कि किस हैश को पुनर्गणना करनी है.

कॅनॉनिकलाइज़ेशन — सरल बनाम रिलैक्स्ड

कॅनॉनिकलाइज़ेशन वह तरीका है जिससे DKIM हैशिंग से पहले संदेश के स्थिर, बाइट‑एक्ज़ैक्ट रूप पर सहमत होता है. दो एल्गोरिद्म हेडर और बॉडी के लिए स्वतंत्र रूप से परिभाषित हैं:

  • Simple — लगभग कोई सामान्यीकरण नहीं. बॉडी में खाली अंत की लाइनों को हटाया जाता है, परंतु अन्य कोई स्पेस नहीं छूटा जाता. एक रिले द्वारा जोड़ी गई एकल स्पेस हस्ताक्षर को अमान्य कर देगी.
  • Relaxed — हेडर मानों के भीतर स्पेस को घटाता है, हेडर नामों को लोअरकेस करता है, और बॉडी में स्पेस की गड्डी को संकुचित करता है. मैल ट्रांसपोर्ट एजेंटों द्वारा किए जाने वाले मामूली पुनःफॉर्मेटिंग को सहन करने योग्य है.

चुनें Relaxed हैडर और बॉडी दोनों के लिए जब तक आपके पास विशेष कारण न हो. लगभग हर उत्पादन परिनियोजन ऐसा करता है.

// Simple canonicalization - almost no changes allowed
var signInfoSimple = new DKIMSignatureInfo("dkim-simple", "example.com")
{
    HeaderCanonicalization = CanonicalizationType.Simple,
    BodyCanonicalization = CanonicalizationType.Simple,
    Headers = { "From", "To", "Subject" }
};

var mailMessage1 = new MailMessage(
    "sender@example.com",
    "recipient@example.com",
    "Simple Canonicalization",
    "This message uses Simple canonicalization.");

mailMessage1.From = new MailAddress("sender@example.com");
var signedSimple = mailMessage1.DKIMSign(rsa, signInfoSimple);

string pathSimple = Path.Combine(DataDir, "simple-canonical.eml");
signedSimple.Save(pathSimple);

// Relaxed canonicalization - minor changes allowed (whitespace normalization)
var signInfoRelaxed = new DKIMSignatureInfo("dkim-relaxed", "example.com")
{
    HeaderCanonicalization = CanonicalizationType.Relaxed,
    BodyCanonicalization = CanonicalizationType.Relaxed,
    Headers = { "From", "To", "Subject" }
};

var mailMessage2 = new MailMessage(
    "sender@example.com",
    "recipient@example.com",
    "Relaxed Canonicalization",
    "This message uses Relaxed canonicalization.");

mailMessage2.From = new MailAddress("sender@example.com");
var signedRelaxed = mailMessage2.DKIMSign(rsa, signInfoRelaxed);

string pathRelaxed = Path.Combine(DataDir, "relaxed-canonical.eml");
signedRelaxed.Save(pathRelaxed);

हेडर और बॉडी कॅनॉनिकलाइज़ेशन स्वतंत्र हैं — relaxed/simple एक पूरी तरह वैध संयोजन है, उसी तरह लिखी गई है c= DKIM हेडर का टैग.

प्राइवेट कुंजी लोड करना

PemReader दोनों PEM एन्कोडिंग को पारदर्शी रूप से संभालता है। कोई अलग नहीं है Pkcs1Reader / Pkcs8Reader — बस पाथ या स्ट्रीम पास करें:

// Check if private key file exists
if (!File.Exists(PrivateKeyPath))
{
    Console.WriteLine($"Private key file not found: {PrivateKeyPath}");
    Console.WriteLine("Creating a sample private key for demonstration...");

    // Create a sample RSA key (for testing only - in production, use real keys)
    using var rsa = new System.Security.Cryptography.RSACryptoServiceProvider(2048);
    var privateKeyParams = rsa.ExportParameters(true);

    Console.WriteLine("Sample RSA key created (2048 bits).");
    Console.WriteLine("In production, load your actual private key from a secure location.");
    Console.WriteLine("PEM file format should contain either:");
    Console.WriteLine("  - BEGIN RSA PRIVATE KEY (PKCS#1)");
    Console.WriteLine("  - BEGIN PRIVATE KEY (PKCS#8)");
}
else
{
    // Load the private key
    var rsa = PemReader.GetPrivateKey(PrivateKeyPath);
    Console.WriteLine($"Private key loaded successfully from: {PrivateKeyPath}");
    Console.WriteLine("Key size: 2048 bits (typical for DKIM)");
}

Console.WriteLine("\nPEM File Format Examples:");
Console.WriteLine("--------------------------");
Console.WriteLine("PKCS#1 format:");
Console.WriteLine("-----BEGIN RSA PRIVATE KEY-----");
Console.WriteLine("MIIEpAIBAAKCAQEA0Z3VS5JJcds3xfn/ygWyF8PbnGy...");
Console.WriteLine("-----END RSA PRIVATE KEY-----");
Console.WriteLine();
Console.WriteLine("PKCS#8 format:");
Console.WriteLine("-----BEGIN PRIVATE KEY-----");
Console.WriteLine("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...");
Console.WriteLine("-----END PRIVATE KEY-----");

PemReader.GetPrivateKey एक लौटाता है RSACryptoServiceProvider हाथ में देने के लिए तैयार DKIMSign. एक भी है GetPrivateKey(Stream) ओवरलोड उन मामलों के लिए जहाँ कुंजी कुंजी भंडार, एन्क्रिप्टेड ब्लॉब, या एम्बेडेड रिसोर्स से आती है, न कि फ़ाइल सिस्टम से.

कुंजी हैंडलिंग नियम:

  1. प्राइवेट कुंजियों को वर्ज़न कंट्रोल में कभी कमिट न करें. *.pem का हिस्सा है .gitignore.
  2. उत्पादन में, कुंजियों को सीक्रेट मैनेज़र (Azure Key Vault, AWS Secrets Manager, HashiCorp Vault) से लोड करें, न कि डिस्क से.
  3. कुंजियों को हर 6–12 महीने में घुमाएँ। पहले नया चयनकर्ता प्रकाशित करें, साइनिंग स्विच करें, फिर एक ग्रेस अवधि के बाद पुराने DNS रिकॉर्ड को हटाएँ.

फ़ाइल से साइन किए गए संदेश को सत्यापित करना

सत्यापन सममित प्रक्रिया है: एक साइन किए गए .eml, DkimVerifier निकालता है DKIM-Signature हेडर, DNS लुकअप करता है <selector>._domainkey.<domain> सार्वजनिक कुंजी के लिए, और हैश को पुनर्गणना करता है। परिणाम है एक DkimResult के साथ IsValid और ErrorMessage.

// For this example, we need a signed message
if (!File.Exists(signedMessagePath))
{
    Console.WriteLine($"Signed message file not found: {signedMessagePath}");
    Console.WriteLine("Please provide a DKIM-signed .eml file for verification.");
    return;
}

// Verify the signature
DkimResult result = DkimVerifier.Verify(signedMessagePath);

// Check the result
if (result.IsValid)
{
    Console.WriteLine("[OK] DKIM signature verification successful!");
    Console.WriteLine("The message was signed by the claimed domain.");
}
else
{
    Console.WriteLine("[FAIL] DKIM signature verification failed!");
    Console.WriteLine($"Error: {result.ErrorMessage}");
}

Console.WriteLine("\nVerification Process:");
Console.WriteLine("1. Extracts DKIM-Signature header from the message");
Console.WriteLine("2. Queries DNS for the public key (selector._domainkey.domain)");
Console.WriteLine("3. Verifies the signature using the public key");
Console.WriteLine("4. Compares computed body hash with the signed body hash");

एक संदेश को सत्यापित करना जो साइन किया गया है d=example.com हमेशा "डिक्शनरी में कुंजी नहीं" या समान DNS‑लुकअप त्रुटि के साथ विफल होगा, क्योंकि example.com DKIM रिकॉर्ड प्रकाशित नहीं करता। वास्तविक सत्यापन परीक्षाओं के लिए आप जिस डोमेन को नियंत्रित करते हैं (या ज्ञात‑अच्छा टेस्ट संदेश) का उपयोग करें.

स्ट्रीम से सत्यापन

जब संदेश डिस्क पर नहीं है — यह IMAP फ़ेच, क्यू, HTTP अपलोड, या ब्लॉब स्टोरेज से आया है — तो उपयोग करें Stream ओवरलोड. यह किसी भी सीखी जा सकने वाली रीड स्ट्रीम को स्वीकार करता है:

// Load the signed message into a stream
using (var stream = File.OpenRead(signedMessagePath))
{
    DkimResult result = DkimVerifier.Verify(stream);

    if (result.IsValid)
    {
        Console.WriteLine("[OK] DKIM signature verified successfully from stream!");
    }
    else
    {
        Console.WriteLine("[FAIL] Verification failed!");
        Console.WriteLine($"Error: {result.ErrorMessage}");
    }
}

Console.WriteLine("\nStream-based verification is useful when:");
Console.WriteLine("  - Working with email from IMAP/POP3 clients");
Console.WriteLine("  - Processing emails from databases or cloud storage");
Console.WriteLine("  - Building web applications that receive emails via HTTP");

Verify(Stream) और Verify(string) फंक्शनली समान हैं — दोनों DNS लुकअप पूरा होने तक ब्लॉक करते हैं। उपयोगकर्ता‑सम्पर्क वाली किसी भी चीज़ के लिए, नीचे दिए गए असिंक्रोनस संस्करणों का उपयोग करें.

असिंक्रोनस सत्यापन

DKIM सत्यापन में DNS राउंड‑ट्रिप शामिल है, जो तेज़ नेटवर्क पर भी कई मिलीसेकंड ले सकता है। ASP.NET अनुरोध हैंडलर, संदेश‑प्रसंस्करण लूप, या किसी UI थ्रेड के भीतर, यह जल्दी से जोड़ जाता है. VerifyAsync एक लौटाता है Task<DkimResult> कि आप await:

if (!File.Exists(signedMessagePath))
{
    Console.WriteLine("Signed message file not found.");
    return;
}

// Async verification
DkimResult result = await DkimVerifier.VerifyAsync(signedMessagePath);

if (result.IsValid)
{
    Console.WriteLine("[OK] Async verification successful!");
}
else
{
    Console.WriteLine("[FAIL] Async verification failed!");
    Console.WriteLine($"Error: {result.ErrorMessage}");
}

Console.WriteLine("\nAsync verification is recommended for:");
Console.WriteLine("  - Web applications (ASP.NET, etc.)");
Console.WriteLine("  - Services that process multiple emails");
Console.WriteLine("  - Any application where you want to avoid blocking the main thread");

एक और भी है VerifyAsync(Stream) ओवरलोड. सिंक API की तरह, विधि घोषित करती है async Task (नहीं async void) — कॉल साइट्स को चाहिए await यह, और कंसोल-ऐप एंट्रीपॉइंट्स कर सकते हैं VerifySignatureAsync().GetAwaiter().GetResult() जब एक async Main उपलब्ध नहीं है.

अंत-से-अंत: लोड, साइन, सहेजें, सत्यापित करें

उपरोक्त टुकड़े एकल कार्यप्रवाह में संयोजित होते हैं। यह वह पूर्ण साइन-एंड-वीरिफ़ाइ पाइपलाइन है जिसे आप लेन-देनात्मक-ईमेल सेवा में एम्बेड करेंगे:

// Step 1: Load private key
var rsa = PemReader.GetPrivateKey(PrivateKeyPath);

// Step 2: Create signature information
var signInfo = new DKIMSignatureInfo("dkim", "example.com")
{
    HeaderCanonicalization = CanonicalizationType.Relaxed,
    BodyCanonicalization = CanonicalizationType.Relaxed,
    HashAlgorithm = DKIMHashAlgorithm.RSASha256,
    Headers =
    {
        "From",
        "To",
        "Subject",
        "Date",
        "MIME-Version"
    }
};

// Step 3: Create email message
var mailMessage = new MailMessage(
    "john.doe@example.com",
    "jane.smith@example.org",
    "Important Document - DKIM Signed",
    "Please find the attached document.\n\nBest regards,\nJohn Doe");

mailMessage.From = new MailAddress("john.doe@example.com", "John Doe");
mailMessage.To.Add(new MailAddress("jane.smith@example.org", "Jane Smith"));
mailMessage.Date = DateTime.UtcNow;
mailMessage.Headers.Add("MIME-Version", "1.0");

// Step 4: Sign the message
var signedMessage = mailMessage.DKIMSign(rsa, signInfo);

// Step 5: Save the signed message
string signedPath = Path.Combine(DataDir, "end-to-end-signed.eml");
signedMessage.Save(signedPath);

// Step 6: Verify the signature
var result = DkimVerifier.Verify(signedPath);

if (result.IsValid)
{
    Console.WriteLine("  [OK] Signature verification successful!");
    Console.WriteLine("  [OK] The message integrity is confirmed.");
    Console.WriteLine("  [OK] The sender domain is authenticated.");
}
else
{
    Console.WriteLine($"  [FAIL] Verification failed: {result.ErrorMessage}");
}

// Step 7: Display DKIM-Signature header
Console.WriteLine("\nStep 7: DKIM-Signature header:");
Console.WriteLine("  " + signedMessage.Headers["DKIM-Signature"]);

एक पूरा DKIM-Signature इस कोड द्वारा उत्पन्न हेडर इस प्रकार दिखता है:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com;
 h=from:to:subject:date:mime-version; q=dns/txt; s=dkim; t=1780252880;
 bh=e2RkwEm0k0yLcVmhi3KeXpt14Ppx3Xx49S33/+J8OGc=;
 b=Zd3sfCGGD9YdOLw1o3YHLFs7DO6V9cc7anye5E3kQ/MEdkU14daTru0sXTZCtCryvJubCs...

दिलचस्प टैग:

  • v=1 — DKIM संस्करण.
  • a=rsa-sha256 — एल्गोरिद्म; दर्शाता है HashAlgorithm.
  • c=relaxed/relaxed — कॅनॉनिकलाइज़ेशन (हेडर/बॉडी).
  • d=example.com / s=dkim — चयनकर्ता और डोमेन; साथ मिलकर वे DNS लुकअप नाम बनाते हैं.
  • h=from:to:subject:date:mime-version — क्रम में साइन किए गए हेडर.
  • bh= — कॅनॉनिकलाइज़्ड बॉडी का बेस64 हैश.
  • b= — कॅनॉनिकलाइज़्ड हेडर पर वास्तविक RSA हस्ताक्षर.

यदि आप कोई भी साइन किए गए हेडर मान बदलते हैं, या बॉडी को संशोधित करते हैं, bh और b अब मेल नहीं खाते और सत्यापन विफल होता है.

DNS में सार्वजनिक कुंजी प्रकाशित करना

स्थानीय रूप से साइन करना केवल आधा काम है। प्राप्तकर्ताओं को सत्यापित करने के लिए, आपके RSA कुंजी की सार्वजनिक प्रतिलिपि को DNS TXT रिकॉर्ड के रूप में यहाँ प्रकाशित किया जाना चाहिए: <selector>._domainkey.<domain>:

Record: dkim._domainkey.example.com
Type:   TXT
Value:  v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBC...

OpenSSL के साथ अपने PEM से सार्वजनिक कुंजी निकालें:

openssl rsa -in sample-private-key.pem -pubout -out sample-public-key.pem

हेडर/फ़ूटर लाइनों को हटाएँ और बेस64 सामग्री को जोड़ें के लिए p= मान. फिर रिकॉर्ड को लाइव होने की पुष्टि करें इससे पहले कि आप उस पर भरोसा करें:

dig dkim._domainkey.example.com TXT

ऑनलाइन टूल जैसे DKIM वैलिडेटर और MXToolbox DKIM चेcker यह आपको बताएगा कि आप द्वारा भेजा गया वास्तविक संदेश अंत-से-अंत सत्यापित किया जा सकता है या नहीं। उत्पादन ट्रैफ़िक को बदलने से पहले उनका उपयोग करें.