public EmailHeader SignMessage(Email email) { // Find the actual headers we're going to sign var headers = email.GetHeadersToSign(_headersToSign); // Generate the header value var value = this.GenerateDkimHeaderValue(email, headers); // Add the signature key headers.Add(new EmailHeader() { Key = SignatureKey, Value = value}); // sign email value += GenerateSignature(email, headers); // Return the new header return new EmailHeader() { Key = SignatureKey, Value = value }; }
/* * see http://www.dkim.org/specs/rfc4871-dkimbase.html#dkim-sig-hdr * * */ public string GenerateDkimHeaderValue(Email email, List<EmailHeader> headers) { // timestamp - seconds since 00:00:00 on January 1, 1970 UTC TimeSpan t = DateTime.Now.ToUniversalTime() - DateTime.SpecifyKind(DateTime.Parse("00:00:00 January 1, 1970"), DateTimeKind.Utc); var signatureValue = new StringBuilder(); var start = /*Email.NewLine + */" "; var end = ";"; //nl= string.Empty; signatureValue.Append("v=1;"); // algorithm used signatureValue.Append(start); signatureValue.Append("a="); signatureValue.Append(_privateKeySigner.Algorithm); signatureValue.Append(end); // Canonicalization signatureValue.Append(start); signatureValue.Append("c="); signatureValue.Append(this.HeaderCanonicalization.ToString().ToLower()); signatureValue.Append('/'); signatureValue.Append(this.BodyCanonicalization.ToString().ToLower()); signatureValue.Append(end); // signing domain signatureValue.Append(start); signatureValue.Append("d="); signatureValue.Append(_domain); signatureValue.Append(end); // headers to be signed signatureValue.Append(start); signatureValue.Append("h="); foreach (var header in headers) { signatureValue.Append(header.Key); signatureValue.Append(':'); } signatureValue.Length--; signatureValue.Append(end); // i=identity // not supported // l=body length //not supported // public key location signatureValue.Append(start); signatureValue.Append("q=dns/txt"); signatureValue.Append(end); // selector signatureValue.Append(start); signatureValue.Append("s="); signatureValue.Append(_selector); signatureValue.Append(end); // time sent signatureValue.Append(start); signatureValue.Append("t="); signatureValue.Append((int)t.TotalSeconds); signatureValue.Append(end); // x=expiration // not supported // hash of body signatureValue.Append(start); signatureValue.Append("bh="); signatureValue.Append(SignBody(email)); signatureValue.Append(end); // x=copied header fields // not supported signatureValue.Append(start); signatureValue.Append("b="); return signatureValue.ToString(); }
/// <summary> /// /// </summary> /// <param name="email">The email to sign.</param> /// <param name="signature"></param> /// <returns></returns> public string GenerateSignature(Email email, List<EmailHeader> headers) { var cheaders = DkimCanonicalizer.CanonicalizeHeaders(headers, this.HeaderCanonicalization); return Convert.ToBase64String(_privateKeySigner.Sign(email.Encoding.GetBytes(cheaders))); }
public string SignBody(Email email) { var cb = DkimCanonicalizer.CanonicalizeBody(email.Body, this.BodyCanonicalization); return Convert.ToBase64String(_privateKeySigner.Hash(email.Encoding.GetBytes(cb))); }
public static string Canonicalize(Email email, DomainKeyCanonicalizationAlgorithm algorithm, List<EmailHeader> headersToSign) { Func<String, string> process; switch (algorithm) { case DomainKeyCanonicalizationAlgorithm.Simple: { process = x => x; break; } case DomainKeyCanonicalizationAlgorithm.Nofws: { process = x => x.RemoveWhitespace(); break; } default: { throw new ArgumentException("Invalid canonicalization type."); } } var headers = new StringBuilder(); foreach (var h in headersToSign) { headers.Append(process(h.Key)); headers.Append(':'); headers.Append(process(" " + h.Value)); headers.Append(Email.NewLine); } var body = new StringBuilder(); using (var reader = new StringReader(email.Body)) { string line; int emptyLines = 0; // if only empty lines don't write until these is text after them while ((line = reader.ReadLine()) != null) { if (line.Length == 0) { emptyLines++; } else { while (emptyLines > 0) { body.Append(Email.NewLine); emptyLines--; } body.Append(process(line)); body.Append(Email.NewLine); } } } // If the body consists entirely of empty lines, then the header/body // line is similarly ignored. if (body.Length == 0) { return headers.ToString(); } headers.Append(Email.NewLine);// header/body seperator line headers.Append(body); return headers.ToString(); }
public EmailHeader SignMessage(Email email) { var signatureValue = new StringBuilder(); // algorithm used signatureValue.Append("a="); signatureValue.Append(_privateKeySigner.Algorithm); signatureValue.Append("; "); // Canonicalization signatureValue.Append("c="); signatureValue.Append(this.Canonicalization.ToString().ToLower()); signatureValue.Append("; "); // signing domain signatureValue.Append("d="); signatureValue.Append(_domain); signatureValue.Append("; "); // headers to be signed var headers = email.GetHeadersToSign(_headersToSign); if (headers.Count>0) { signatureValue.Append("h="); foreach (var header in headers) { signatureValue.Append(header.Key); signatureValue.Append(':'); } signatureValue.Length--; signatureValue.Append("; "); } // public key location signatureValue.Append("q=dns; "); // selector signatureValue.Append("s="); signatureValue.Append(_selector); signatureValue.Append("; "); // signature data signatureValue.Append("b="); signatureValue.Append(SignSignature(email, headers)); signatureValue.Append(";"); return new EmailHeader() { Key = SignatureKey, Value = signatureValue.ToString() }; }
public string SignSignature(Email email, List<EmailHeader> headers) { var text = DomainKeyCanonicalizer.Canonicalize(email, this.Canonicalization, headers); return Convert.ToBase64String(_privateKeySigner.Sign(email.Encoding.GetBytes(text))); }
void FinishCollecting() { if (m_CollectMode == CollectMode.None) return; var e = new Email() { Headers = m_collectedHeaders, Body = m_collectedContent.ToString(), Encoding = writer.Encoding }; // Generate Dkim signature if (DkimSigner != null) { m_collectedHeaders.Insert(0, DkimSigner.SignMessage(e)); } // Generate domain keys signature if (DomainKeysSigner != null) { m_collectedHeaders.Insert(0, DomainKeysSigner.SignMessage(e)); } m_CollectMode = CollectMode.None; // Write all headers foreach (var h in m_collectedHeaders) { SendHeader(h.Key, h.Value); } // Write the separator SendData(string.Empty); // Write the content SendData(e.Body); }
public string SignSignature(Email email, List <EmailHeader> headers) { var text = DomainKeyCanonicalizer.Canonicalize(email, this.Canonicalization, headers); return(Convert.ToBase64String(_privateKeySigner.Sign(email.Encoding.GetBytes(text)))); }