public static bool Verify(byte[] emailData, Signature signature)
        {
            string emailDatastr = Encoding.ASCII.GetString(emailData, 0, emailData.Length);
            string header       = emailDatastr.Substring(0, emailDatastr.IndexOf("\r\n\r\n"));

            header = Parser.Unfold(header);
            header = SelectFieldsAndCanonicalize(header, signature);
            string body = emailDatastr.Substring(Regex.Match(emailDatastr, @"(?<=\r?\n\r?\n).").Index - 1);

            System.IO.StringReader sr = new System.IO.StringReader(body);
            StringBuilder          sb = new StringBuilder();

            while (sr.Peek() != -1)
            {
                sb.Append(string.Concat(Canonicalizer.Canonicalize(sr.ReadLine(), signature.CanonicalizationAlgorithm), Tokenizer.NewLine));
            }
            byte[] canonicalized = Encoding.ASCII.GetBytes(header + sb.ToString().TrimEnd('\r', '\n') + "\r\n");

            SHA1Managed sha = new SHA1Managed();

            byte[] hash = sha.ComputeHash(canonicalized);

            PublicKeyRecord record = signature.GetPublicKeyRecord();

            RSACryptoServiceProvider rsa  = new RSACryptoServiceProvider();
            RSAParameters            rsap = new RSAParameters();

            FillRSAPublicKeyParameters(record.KeyData, ref rsap);
            rsa.ImportParameters(rsap);
            RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(rsa);

            RSADeformatter.SetHashAlgorithm("SHA1");

            return(RSADeformatter.VerifySignature(hash, signature.Data));
        }
        private static string SelectFieldsAndCanonicalize(string header, Signature signature)
        {
            // Make a lowercase version for easy IndoxOf.
            string headerLower = header.ToLower();

            // We will only review the portion of the header after (before, in time) the signature.
            int start = headerLower.IndexOf("\ndomainkey-signature");

            header = header.Substring(start);

            StringBuilder sb = new StringBuilder();

            // Unfold.
            header = Parser.Unfold(header);

            // Build a list of header lines.
            string[] lines = Regex.Split(header, "\r?\n");

            // Do we have to take specific headers or all headers ?
            if (signature.SignedHeaders.Length > 0)
            {
                // There are specific headers. For each field name in the signature, loop through the lines and append found occurences.
                foreach (string str in signature.SignedHeaders)
                {
                    foreach (string line in lines)
                    {
                        if (line.ToLower().StartsWith(str))
                        {
                            sb.Append(string.Concat(Canonicalizer.Canonicalize(line, signature.CanonicalizationAlgorithm), Tokenizer.NewLine));
                        }
                    }
                }
            }
            else
            {
                // We take all headers subsequent to the signature field.
                bool firstPassed = false;
                foreach (string line in lines)
                {
                    if (!firstPassed)
                    {
                        firstPassed = true;
                        continue;
                    }
                    else
                    {
                        sb.Append(string.Concat(line, Tokenizer.NewLine));
                    }
                }
            }

            return(sb.ToString().TrimEnd('\r', '\n') + "\r\n");
        }