简体   繁体   English

无法验证DKIM的主体哈希

[英]Unable to verify body hash for DKIM

I'm writing a C# DKIM validator and have come across a problem that I cannot solve. 我正在编写C#DKIM验证器,遇到了无法解决的问题。 Right now I am working on calculating the body hash, as described in Section 3.7 Computing the Message Hashes . 现在,我正在计算主体哈希,如3.7节“计算消息哈希”中所述 I am working with emails that I have dumped using a modified version of EdgeTransportAsyncLogging sample in the Exchange 2010 Transport Agent SDK. 我正在使用在Exchange 2010传输代理SDK中使用EdgeTransportAsyncLogging示例的修改版转储的电子邮件。 Instead of converting the emails when saving, it just opens a file based on the MessageID and dumps the raw data to disk. 它不会在保存时转换电子邮件,而只是打开一个基于MessageID的文件并将原始数据转储到磁盘。

I am able to successfully compute the body hash of the sample email provided in Section A.2 using the following code: 我可以使用以下代码成功计算A.2节中提供的示例电子邮件的正文哈希:

SHA256Managed hasher = new SHA256Managed();
ASCIIEncoding asciiEncoding = new ASCIIEncoding();
string rawFullMessage = File.ReadAllText(@"C:\Repositories\Sample-A.2.txt");
string headerDelimiter = "\r\n\r\n";
int headerEnd = rawFullMessage.IndexOf(headerDelimiter);
string header = rawFullMessage.Substring(0, headerEnd);
string body = rawFullMessage.Substring(headerEnd + headerDelimiter.Length);
byte[] bodyBytes = asciiEncoding.GetBytes(body);
byte[] bodyHash = hasher.ComputeHash(bodyBytes);
string bodyBase64 = Convert.ToBase64String(bodyHash);
string expectedBase64 = "2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=";
Console.WriteLine("Expected hash: {1}{0}Computed hash: {2}{0}Are equal: {3}",
  Environment.NewLine, expectedBase64, bodyBase64, expectedBase64 == bodyBase64);

The output from the above code is: 上面代码的输出是:

Expected hash: 2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=
Computed hash: 2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=
Are equal: True

Now, most emails come across with the c=relaxed/relaxed setting, which requires you to do some work on the body and header before hashing and verifying. 现在,大多数电子邮件都有c=relaxed/relaxed设置,这要求您在哈希和验证之前对正文和标头进行一些处理。 And while I was working on it (failing to get it to work) I finally came across a message with c=simple/simple which means that you process the whole body as is minus any empty CRLF at the end of the body. 当我在进行处理时(未能使其正常工作),我最终遇到了一条消息,消息中带有c=simple/simple ,这意味着您像处理整个正文一样减去正文末尾的任何空CRLF (Really, the rules for Body Canonicalization are quite ... simple .) (确实,身体规范化的规则相当…… 简单 。)

Here is the real DKIM email (right click and save it, the browsers eat the ending CRLF ) with a signature using the simple algorithm (completely unmodified). 这是真正的DKIM电子邮件 (右键单击并保存,浏览器使用结尾的CRLF ),并使用简单算法(完全未经修改)签名。 Now, using the above code and updating the expectedBase64 hash I get the following results: 现在,使用上面的代码并更新expectedBase64哈希,我得到以下结果:

Expected hash: VnGg12/s7xH3BraeN5LiiN+I2Ul/db5/jZYYgt4wEIw=
Computed hash: ISNNtgnFZxmW6iuey/3Qql5u6nflKPTke4sMXWMxNUw=
Are equal: False

The expected hash is the value from the bh= field of the DKIM-Signature header. 预期的哈希是DKIM-Signature标头的bh=字段中的值。 Now, the file used in the second test is a direct raw output from the Exchange 2010 Transport Agent. 现在,第二项测试中使用的文件是Exchange 2010传输代理的直接原始输出。 If so inclined, you can view the modified EdgeTransportLogging.txt . 如果愿意,可以查看修改后的EdgeTransportLogging.txt

At this point, no matter how I modify the second email, changing the start position or number of CRLF at the end of the file I cannot get the files to match. 此时,无论我如何修改第二封电子邮件,更改文件末尾的CRLF起始位置或编号,都无法使文件匹配。 What worries me is that I have been unable to validate any body hash so far (simple or relaxed) and that it may not be feasible to process DKIM through Exchange 2010. 令我担心的是,到目前为止,我仍然无法验证任何正文哈希(简单或轻松),并且可能无法通过Exchange 2010处理DKIM。

I tried this in python-dkim and I get a body hash mismatch too. 我在python-dkim中尝试了此操作,但我也得到了正文哈希不匹配。

I think probably Exchange's GetMimeReadStream is not giving you the actual bytes as they were transmitted, therefore the hash doesn't match. 我认为,Exchange的GetMimeReadStream可能不会在传输时给您实际的字节,因此哈希值不匹配。 Probably it's disassembling the message into its mime parts, and then GetMimeReadStream gives you a valid representation of the message, but not the one it was originally sent with. 可能是将消息分解成其mime部分,然后GetMimeReadStream为您提供了消息有效表示形式,但没有给它最初发送的消息形式。

Perhaps there's another API that will give you the real raw bytes? 也许还有另一个API可以为您提供真实的原始字节?

Or perhaps by this point in the process the message has been torn apart and the original message thrown away, and you need to hook in earlier. 或者,可能在此过程中,邮件已被撕裂,原始邮件已被丢弃,您需要更早加入。

Probably you should try intercepting a DKIM-signed message by sending it to a non-Exchange server, and see if that works with your code. 可能您应该尝试通过将DKIM签名的消息发送到非Exchange服务器来拦截该消息,并查看该代码是否适用于您的代码。 GetContentReadStream might possibly work? GetContentReadStream可能可行吗?

Anyhow, what I would do next is try to find an API that gives you byte-for-byte what was sent. 无论如何,我接下来要做的就是尝试找到一个API,该API逐字节提供所发送的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM