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"); }