Example #1
0
 /// <summary>
 /// Builds an unsigned DKIM-Signature header. Note that the returned
 /// header will NOT have a CRLF at the end.
 /// </summary>
 /// <param name="bodyHash">The hash of the body.</param>
 /// <returns>The unsigned DKIM-Signature header.</returns>
 private string GetUnsignedDkimHeader(DomainElement domain, string bodyHash)
 {
     return(string.Format(
                CultureInfo.InvariantCulture,
                "DKIM-Signature: v=1; a={0}; s={1}; d={2}; c={3}/{4}; q=dns/txt; h={5}; bh={6}; b=;",
                this.hashAlgorithmDkimCode,
                domain.getSelector(),
                domain.getDomain(),
                this.headerCanonicalization.ToString().ToLower(),
                this.bodyCanonicalization.ToString().ToLower(),
                string.Join(" : ", this.eligibleHeaders.OrderBy(x => x, StringComparer.Ordinal).ToArray()),
                bodyHash));
 }
Example #2
0
        /// <summary>
        /// Gets the version of the DKIM-Signature header with the signature appended, along with
        /// the CRLF.
        /// </summary>
        /// <param name="unsignedDkimHeader">The unsigned DKIM header, to use as a template.</param>
        /// <param name="canonicalizedHeaders">The headers to be included as part of the signature.</param>
        /// <returns>The signed DKIM-Signature header.</returns>
        private string GetSignedDkimHeader(DomainElement domain, string unsignedDkimHeader, IEnumerable <string> canonicalizedHeaders)
        {
            byte[]        signatureBytes;
            string        signatureText;
            StringBuilder signedDkimHeader;

            if (domain.CryptoProvider == null)
            {
                throw new Exception("CryptoProvider for domain " + domain.getDomain() + " is null.");
            }

            using (var stream = new MemoryStream())
            {
                using (var writer = new StreamWriter(stream))
                {
                    foreach (var canonicalizedHeader in canonicalizedHeaders)
                    {
                        writer.Write(canonicalizedHeader);
                    }

                    if (this.headerCanonicalization == DkimCanonicalizationKind.Relaxed)
                    {
                        unsignedDkimHeader = Regex.Replace(unsignedDkimHeader, @" ?: ?", ":");
                        string[] temp = unsignedDkimHeader.Split(new char[] { ':' }, 2);
                        unsignedDkimHeader = temp[0].ToLower() + ":" + temp[1];
                    }

                    writer.Write(unsignedDkimHeader);
                    writer.Flush();

                    stream.Seek(0, SeekOrigin.Begin);

                    // Why not pass this.hashAlgorithm here, since we already have it? If we're supporting
                    // Exchange 2007, then we're stuck on CLR 2.0. The SHA-256 functionality was added in
                    // .NET 3.5 SP1, but it was done in such a way that the switch statement used internally
                    // by the Crypto .NET classes won't recognize the new SHA256CryptoServiceProvider type.
                    // So, we have to use the string method instead. More details available at
                    // http://blogs.msdn.com/b/shawnfa/archive/2008/08/25/using-rsacryptoserviceprovider-for-rsa-sha256-signatures.aspx
                    signatureBytes = domain.CryptoProvider.SignData(stream, this.hashAlgorithmCryptoCode);
                }
            }

            signatureText    = Convert.ToBase64String(signatureBytes);
            signedDkimHeader = new StringBuilder(unsignedDkimHeader.Substring(0, unsignedDkimHeader.Length - 1));
            signedDkimHeader.Append(signatureText);
            signedDkimHeader.Append(";\r\n");

            return(signedDkimHeader.ToString());
        }