brutaldev / StrongNameSigner

Strong-name sign third party .NET assemblies without the source code.
https://brutaldev.com/post/net-assembly-strong-name-signer
Other
320 stars 68 forks source link

Fixing up references sometimes invalidates the assembly #8

Closed Bringer128 closed 9 years ago

Bringer128 commented 9 years ago

Hey there,

I have a scenario where I have 3 assemblies that need to be referenced by a strong-name signed project. One is a 3rd party library and 2 are created by me, but I don't want to make them strong-name signed.

What I've found is that in my case, MyLib2.dll is correctly compiled, but when loaded I get the error:

Could not load file or assembly 'MyLib2' or one of its dependencies. Strong name signature could not be verified. The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT: 0x80131045)

I've narrowed this error down to this line: https://github.com/brutaldev/StrongNameSigner/blob/59ea220c10fa04ebff3360fb737fbcb2f78de5b1/src/Brutal.Dev.StrongNameSigner/SigningHelper.cs#L249

If I set a breakpoint before this line and use "sn.exe -v MyLib2.dll" it responds saying MyLib2.dll is valid. If I then step over this line and check again with sn.exe it responds with the "String name signature could not be verified".

I then did a quick test by hardcoding this line to this:

a.Write(assemblyPath, new WriterParameters { StrongNameKeyPair = GetStrongNameKeyPair("C:\\path\\to\\MyKeyPair.snk", null) });

And this causes the problem to disappear.

Unfortunately I haven't had time yet to create a simple failing test case but it looks to me to be a fairly simple change. I'll have a look tomorrow about coming up with a failing unit test and a pull request to fix it.

brutaldev commented 9 years ago

Hey,

Thanks for the detailed report. I'm a bit confused as to why you don't want your assemblies signed but you do want the third party assembly signed?

That error would typically happen if MyLib2 is referenced by something and now the strong-name has changed. Your code sample provided is probably using the same key that you used to sign MyLib2 originally, the the assembly referencing it will still see the correct signature.

Try passing in your strong-name key file when signing everything. That means that other assemblies that are not being processed by the StrongNameSigner will still see the same signature on the files that you are signing again. This does mean that ThirdPartyLib.dll will be using your strong name as well.

When you sign ThirdPartyLib.dll, the reference that MyLib2 has on it also needs to be changed. THis effectively "tampers" with MyLib2, which means you need to sign it again. If you don't sign it with the same key as you did during a build, then anything using MyLib2 (such as your executable) will now have the incorrect strong name reference to the file.

To overcome this, you should either provide the same strong name key pair file to re-sign the MyLib assemblies, or include everything that is referencing re-signed files so that they can all be corrected.

Let me know if this makes sense and is relevant. Creating a test using the steps described above will also result in the same error message.

Werner

Bringer128 commented 9 years ago

Hi again and thanks for the prompt response.

I wasn't clear enough in the original issue but I am trying to integrate 3 assemblies (2 written by me) into a project that must be strong named. I don't want to put strong naming into the build process for the 3 assemblies, therefore I am using this (awesome) tool. :)

When you sign ThirdPartyLib.dll, the reference that MyLib2 has on it also needs to be changed. THis effectively "tampers" with MyLib2, which means you need to sign it again.

That is what I'm seeing here, I think the problem is that the Console and UI executables for StrongNameSigner do not re-sign with the same key when they tamper with the assembly. This makes sn.exe -v tell me that MyLib and MyLib2 fail their strong-name validation.

I think the correct fix will be to add an overload to FixAssemblyReference that the UI and Console app can pass down the StrongNameKeyPair that was used to originally sign the assembly. This will enable StrongNameSigner.SignerHelper to correctly update the assembly.

I'll be investigating creating a minimal test case shortly. :)

Bringer128 commented 9 years ago

I'm having trouble creating a repro scenario in a test; any test assemblies I look at or create appear to work correctly.

I'm not familiar with the inner workings of the assembly format etc. that is operated on by Mono Cecil stuff so I might have to look at this again on the weekend. Thanks for your help so far.

brutaldev commented 9 years ago

Thanks, I reviewed, merged your fixes and released a new version. https://github.com/brutaldev/StrongNameSigner/releases/tag/1.4.3

Don't worry about the test case, I can't get this to happen either but the code change makes sense.