# Why do SignTool/Authenticode Message Digests not match the direct hash of the file?

I'm attempting to validate an Authenticode signature (generated by signtool /fd SHA256 /f <code signing PFX> /p <PFX password> test.exe), and I've run into an issue that I've narrowed down to a single point of confusion.

For the command above, if I hash test.exe before running the signing operation, for example using Get-FileHash test.exe in Powershell, I get a SHA256 hash of the file. But after signing the file, inspecting the signature in windows (Properties -> Digital Signatures -> Details -> Advanced) shows a "Message Digest" value which is entirely different from the hash of test.exe as calculated before signing.

Windows reports this signature as valid, so there is clearly a consistent understanding of "Message Digest" that isn't the one I have in my head (hash of the raw file contents, excluding signature). Can somebody please explain to me what Message Digest means in this context, and how it differs from a regular hashing operation?

• I guess the signature is attached to the file, which changes the outcome of the hash applied to it. – DannyNiu Apr 4 at 5:14
• Sorry if I wasn't clear - the signature is definitely attached to the file and does change the hash, but I wasn't expecting the raw hash of the file after signing to stay the same or match the Message Digest field inside the signature (that would require finding a very specific collision every time). What I expect to see is pre-signing hash == Message Digest inside the signature properties. – Luke Kennedy Apr 4 at 5:17
• There's no particular reason why the message digest shouldn't include some additional meta information. It probably comes down to the exact specification of the tool you're using. But that I would think is off topic here. – Maeher Apr 4 at 8:48

You are expecting that the hash that is produced is always over the complete file. This is not correct. Authenticode uses the Cryptographic Message Syntax - a container format - to embed the content and the signature. This ensures that the Authenticode signature is using the hash of the original data (+ other signed attributes). The Authenticode format is specified here.

To quote:

A PKCS#7 SignedDatastructure contains the PE file's hash value, a signature created by the software publisher’s private key, and the X.509 v3 certificates that bind the software publisher’s signing key to a legal entity. A PKCS#7 SignedDatastructure can optionally contain:

• A description of the software publisher.
• The software publisher's URL.
• An Authenticode timestamp.

Note that Microsoft keeps interchanging the name of the standard with the name of the structure that it defines: PKCS#7 is the standard that defines the Cryptographic Message Syntax.

Unfortunately, going through all the steps of "Calculating the PE Image Hash" is a bit too much for this answer; if you plan to do this programmatically you could ask questions about it on StackOverflow.

• I'll never get over the stupidity of creating a class called Rfc2898DeriveBytes to implement PBKDF2 – Maarten Bodewes Apr 4 at 13:30
• Oh! I absolutely had not made the connection between Authenticode and PKCS#7 in the documentation of SignTool. I knew it was possible to output signatures as PKCS#7, but not that they always were behind the scenes embedded in files. I did realise that the hash would produced over the original data (not the complete signed file), but not that other signed attributes were included, I'll brush up on RFC 2315 and the Authenticode document you linked. Thank you. – Luke Kennedy Apr 4 at 13:32
• Fortunately Microsoft at least created that PDF document for us to read. OK, it is full of proprietary structures, but it is at least using a well defined standard and they did try to document it to the best of their abilities. I have to give credit to MS as well instead of just bashing them (which, in my opinion, they often do deserve). – Maarten Bodewes Apr 4 at 13:35