Alois Kraus

blog

  Home  |   Contact  |   Syndication    |   Login
  106 Posts | 8 Stories | 294 Comments | 162 Trackbacks

News



Article Categories

Archives

Post Categories

Image Galleries

Programming

Strong naming has always been a complicated matter.  Sometimes it is even impossible when you get unsigned assemblies from a third party software vendor and you have to build strong named assemblies to install them into the GAC. When you decide to strong name your project it is a all or nothing decision. If your target is strong named then all references must also be strong named. If you do not have the source code and a project for your third party dll you will not be able to sign your project. I have created Signer which is hosted at CodePlex that allows you to add strong names to binaries within minutes. You can even create a strong named build of your whole project without any changes to your build settings. Below is a picture which shows Signer in action:

Signer

How does it work?

Signer does basically a full round trip by decompiling the assembly into IL code make the necessary modifications and compile it back to a valid assembly. The required modifications include
  • Update of all references
  • Change/Removal of InternalsVisibleToAttribute
  • Update of custom attributes with a type parameter
  • A little fix to work around an ILDASM problem
Reference Update in IL

This is the easy part. A reference does consist of the assembly name, public key token and it's version. Signer has only to insert the public key token where none is present to patch the IL file.

.assembly extern Microsoft.Practices.EnterpriseLibrary.Common
{
  .publickeytoken = (BE CA 05 5E 5B 7D 2D C8 ) // Inserted by Signer if not present
  .ver 2:0:0:0
}

InternalsVisibleTo Attribute

With .NET 2.0 the InternalsVisibleTo attribute was introduced that allows to grant other assemblies access to classes and methods marked with the internal keyword. To prevent in a strong name scenario that an unsigned assembly does get access to internals directly (you can use reflection instead but this comes with a perf cost) the CLR does check at runtime if all InternalsVisibleTo attribute declarations grant access to strong named assemblies only. If not a runtime exception is thrown and the process terminates.

.custom  instance void [mscorlib]System.Runtime.CompilerServices.InternalsVisibleToAttribute::.ctor(string)  =
                              ( 01 00 48 4D 69 63 72 6F 73 6F 66 74 2E 50 72 61   // ..HMicrosoft.Pra
                                63 74 69 63 65 73 2E 45 6E 74 65 72 70 72 69 73   // ctices.Enterpris
                                65 4C 69 62 72 61 72 79 2E 4C 6F 67 67 69 6E 67   // eLibrary.Logging
                                2E 43 6F 6E 66 69 67 75 72 61 74 69 6F 6E 2E 44   // .Configuration.D
                                65 73 69 67 6E 2E 54 65 73 74 73 00 00 )          // esign.Tests.."


You have to insert the public key which is over 300 bytes long into your project which is quite tedious if you want to do it manually. At the moment Signer makes life easy and simply removes the attribute to prevent run time errors but if needed the change is trivial.

Custom Attributes
This was by far the most tricky part. When you declare custom attributes with a type parameter the full qualified type name including assembly and public key token is inserted into the IL code. Normally you get this as a binary blob but with the /CAVERBAL option of ILDASM which was introduced with .NET 2.0 things get much easier.

.custom instance void [System]System.ComponentModel.EditorAttribute::.ctor(class [mscorlib]System.Type,
                                                                           class [mscorlib]System.Type)
      = {
         type(class
              'Microsoft.Practices.EnterpriseLibrary.Configuration.Design.ReferenceEditor,
               Microsoft.Practices.EnterpriseLibrary.Configuration.Design, Version=2.0.0.0, Culture=neutral,
               PublicKeyToken=beca055e5b7d2dc8')
         type(class
              'System.Drawing.Design.UITypeEditor, System.Drawing, Version=2.0.0.0, Culture=neutral,
               PublicKeyToken=b03f5f7f11d50a3a')
        }


Signer does parse the attributes and does set the PublicKeyToken where needed.

ILDASM Problems
All would work wonderful if, well if the nice /CAVERBAL option would produce running code. But I got many ConfiguratonErrors exceptions which told me that the default value was of the wrong type. Arghhh. After digging a little deeper I found out what was going on. Suppose you have a simple configuration class for settings inside the App.Config file:

using System;

using System.Collections.Generic;

using System.Text;

using System.Configuration;

 

namespace NoRoundTrip

{

    enum MyValues

    {

        V1

    }

 

    class Check : ConfigurationSection

    {

        const string PropName = "Name";

 

        // DefaultValue is a property of type object

        [ConfigurationProperty(PropName,DefaultValue=MyValues.V1)]

        public MyValues Value

        {

            get { return (MyValues) this[PropName]; }

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            Check c = new Check();

            MyValues defValue = c.Value;  // get default value

        }

    }

}


The program will work without problem when used as is. But after decompiling with the /CAVERBAL option and recompiling you will get a nasty runtime exception:

Unhandled Exception: System.Configuration.ConfigurationErrorsException:
                                     The default value for the property 'Name' has different type than the one of the property itself.


Here is the innocent looking IL code
    .custom instance void
          [System.Configuration]System.Configuration.ConfigurationPropertyAttribute::.ctor(string)

                = {
                      string('Name')

                      property object 'DefaultValue' = object( int32(0) )
                  }


The ConfigurationProperty DefaultValue does not preserve type identity for enums but does simply declare them as its native integer value which will lead to this exception during run time because there is an extra check code in the BCL code. The generated IL code is valid for the CLR but not for the BCL. Signer does get around this issue by decompiling every assembly once with the parser friendly /CAVERBAL option and the second time without. It will then merge the binary blobs for the ConfigurationProperty Attributes into the other IL file to get a fully functional assembly. Once this obstacle was solved all worked perfectly.

Signer Usage

If you start Signer without any options you will get a pretty self explanatory help to do signing. The only thing to remeber is that the .NET Framework tool sn  is needed to generate a strong name key pair by simply executing sn -k c:\key.snk and you are ready to use Signer out of the box with your project.

Signer (C) by Alois Kraus 2007 (akraus1@gmx.de) version 1.0.0.0

Signer -k <KeyFile> -outdir <Output Dir> -a <Assembly1> <Assembly2> ... [-decomp "Options" -comp "Options" -debug]
   Signer does sign all assemblies and updates their references if the assembly is not already signed
   This way you can convert a whole bunch of assemblies which have never seen a key file into strong named assemblies without recompiling!
   -k        Key File name of key container file which is created usually by the sign tool (sn -k)
   -outdir   Output directory where the strong signed assemblies are copied to
   -decomp   Additional ildasm options e.g. "/STATS"
   -comp     Additional ilasm options e.g. "/X64"
   -a        Can be a list of assembly names or a wildcard search pattern e.g. *.dll
   -debug    Do not delete temporary IL files in %TEMP% flder after completion

 Example: Signer -k c:\key.snk -outdir .\build -a *.dll *.exe  Copy the signed assemblies into the newly created directory build.
 Example: Signer -k c:\key.snk -outdir . -a *.dll *.exe        Sign and overwrite the orignal binaries in current directory.

Error: No Key file specifed (use -k KeyFile ).
Error: No Output directory specifed (use -outdir Dir ).
Error: No input assemblies specified (use -a Assembly ).


Conclusions

It was fun to create the tool while learning quite a lot about the assembly structure, strong names and IL. As you can see strong names are not really a protection for your software as they can be easily removed and your assemblies resigned without big problems. The only real advantage strong names offer is that you can prove that an assembly which has your public key on it was created by you as long as your secret key is kept safe.
From this point other extensions to Signer are quite easy to add. E.g. removal of strong names, make internals public or adding your own InternalsVisibleTo attribute to other assemblies. The world is full of possibilities ;-).
posted on Tuesday, January 23, 2007 2:21 PM

Feedback

# re: Create Strong Named Assemblies - The Easy Way 1/29/2007 3:28 PM Nordin Rahman
Congratulations Alois,

"The program will work without problem when used as is. But after decompiling with the /CAVERBAL option and recompiling you will get a nasty runtime exception:"

I believe it took you very long time to figure out this. Thanks for sharing your experience with us, and, thanks for the tool.

I can say that, IMHO, your tool is at par as Andrea Bertolotto's Strong Name Remover (as it compliment each other).

Thanks again.

# re: Create Strong Named Assemblies - The Easy Way 1/29/2007 11:17 PM Alois Kraus
Thanks Rhaman.

This exception was quite helpful and took not so long to figure out what was going on. But the most problematic part was to discover that I was not done by simply replacing the references in the file header with the public key token for each unsigned assembly. There are other locations inside an assembly that need attention. To write the correct parsing logic and to find the caverbal option to decompile these nasty blobs into something more or less easy parsable was something that did take quite a while.
For features I plan to add InternalsVisible support and eventually strong naming removal which is quite easy when you have the IL file already in place.

Yours,
Alois Kraus


# re: Create Strong Named Assemblies - The Easy Way 2/28/2007 3:44 PM Peter Lemmen
Hi Alois,
I've tried your tool on a simple HelloWorld Class Lib. I've used these commands:

sn -k test.snk
signer -k test.snk -outdir c:\data -a TestSigning.dll -debug

It gave me this error:

An unexpected processing error did occur: System.IO.InvalidDataException: Could
not convert public key blob to a public key token. Error code: -2146893788
at Signer.Executor.DeterminePublicKeyTokenFromKeyFile(String keyFile)
at Signer.Program.Execute()
at Signer.Program.Main(String[] args)

I would realy want to use your tool for using a unsigned third party DLL from my signed assemblies. Any idea about what i'm doing wrong?

Regards,

Peter Lemmen
Amsterdam
Netherlands

# re: Create Strong Named Assemblies - The Easy Way 2/28/2007 7:41 PM Alois Kraus
Do you use a Key Container file? If you create a key/pair with sn -k outKeyFile.snk it should not give you such an error. It sounds like the key file does contain invalid data or is in the wrong format.

Yours,
Alois Kraus



# re: Create Strong Named Assemblies - The Easy Way 3/29/2007 2:21 PM EricBlair
Hello,

Nice program! I tried it and immediately I get the following error:
Execute of ildasm.exe /? failed
An unexpected processing error did occur: System.NullReferenceException: Object
reference not set to an instance of an object.
at Signer.Executor.GetInvalidCommands()
at Signer.Program.Execute()
at Signer.Program.Main(String[] args)

Here is my command line:
c:\signer\signer.exe -k Moz1Keyfile.pfx -outdir c:\signer -a UnsignedLib.dll

Am I missing something here?

Thanks!


# re: Create Strong Named Assemblies - The Easy Way 3/29/2007 9:35 PM EricBlair
Never mind, I'm not using the right key file type. All set, thank you!

# re: Create Strong Named Assemblies - The Easy Way 3/30/2007 3:33 PM Bull
It did not work for me(or IrrKlang.NET.dll)
I downloaded the latest version of irrklang from amberia.net.
Then i did:
sn -k key.snk
signer -k key.snk -outdir test -a IrrKlang.NET.dll

I got the error:


Execute of corflags.exe failed

Execute of ildasm.exe /? failed
An unexpected processing error did occur: System.NullReferenceException: Object
reference not set to an instance of an object.
at Signer.Executor.GetInvalidCommands()
at Signer.Program.Execute()
at Signer.Program.Main(String[] args)

# re: Create Strong Named Assemblies - The Easy Way 3/31/2007 9:28 AM Alois Kraus
You could check what the output of corflags.exe is if you execute on your shell:

corflags IrrKlang.NET.dll

If the file is not 0 bytes big and you use the .NET 2.0 corflags exe it should work.

Yours,
Alois Kraus


# re: Create Strong Named Assemblies - The Easy Way 4/13/2007 2:29 AM lvildosola
The tool does not seem to work with delay signed assemblies. I get the following message:

Info: Assembly <assembly> is already signed. Ignore.

Is there a special switch for delay signing? Similar to the SN -R switch.

# re: Create Strong Named Assemblies - The Easy Way 7/5/2007 2:10 AM Jerome
Really nice work, thank you!

# re: Create Strong Named Assemblies - The Easy Way 7/24/2007 11:18 AM Ed Stone
Ho do I get?

# re: Create Strong Named Assemblies - The Easy Way 8/2/2007 5:35 AM Adam
Seems pretty straightforward to use but im getting a Warning that says DLL is either unmanaged or has 0 byte length. Ignored

What does this mean, i know its not 0 byte length, do unmanaged dlls not need to be strong named to be truster???

Still trying to figure out the whole trust thing with signing...

# re: Create Strong Named Assemblies - The Easy Way 8/2/2007 7:19 AM Alois Kraus
You can sign any file/EMail (e.g. with Authenticode) but strong assembly names are a feature of the .NET Framework only for which my Signer tool was designed for.

Yours,
Alois Kraus


# re: Create Strong Named Assemblies - The Easy Way 8/8/2007 3:15 AM Raj
I successfully signed all my unsigned assemblies but the version number also got updated on them. Is there a way to sign the dlls without updating the version number?

Thanks

# re: Create Strong Named Assemblies - The Easy Way 9/6/2007 12:52 AM Edwin
Looks like a great, but can't get it working.
Generated a key-file as stated and tried the tool:

Signer -k C:\test.snk -outdir C:\Signer -a Test.exe which gave me the following error:

Execute of corflags.exe failed

Execute of ildasm.exe /? failed
An unexpected processing error did occur: System.NullReferenceException: Object
reference not set to an instance of an object.
at Signer.Executor.GetInvalidCommands()
at Signer.Program.Execute()
at Signer.Program.Main(String[] args)

If I run corflags on the exe it says:
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 1
ILONLY : 1
32BIT : 0
Signed : 0


Seems to me that the snk file is correct, the version of corflags is v2.x and the size is bigger than 0 bytes.

Any idea what's going wrong?

# re: Create Strong Named Assemblies - The Easy Way 9/6/2007 12:52 AM Edwin
Looks like a great, but can't get it working.
Generated a key-file as stated and tried the tool:

Signer -k C:\test.snk -outdir C:\Signer -a Test.exe which gave me the following error:

Execute of corflags.exe failed

Execute of ildasm.exe /? failed
An unexpected processing error did occur: System.NullReferenceException: Object
reference not set to an instance of an object.
at Signer.Executor.GetInvalidCommands()
at Signer.Program.Execute()
at Signer.Program.Main(String[] args)

If I run corflags on the exe it says:
Version : v2.0.50727
CLR Header: 2.5
PE : PE32
CorFlags : 1
ILONLY : 1
32BIT : 0
Signed : 0


Seems to me that the snk file is correct, the version of corflags is v2.x and the size is bigger than 0 bytes.

Any idea what's going wrong?

# re: Create Strong Named Assemblies - The Easy Way 9/6/2007 1:35 AM Edwin
Ok, I found the solution.

Opened the source and found out that line (103) only works if ILDASM is found. Else res.StdOut == NULL:

string majorVersion = res.StdOut.Substring(res.StdOut.IndexOf("Version", StringComparison.InvariantCulture) + 8, 1);

Builtin a check for this and now the normal errors will appear on the screen saying that the needed executables where not found (corflags, ildasm, ...).

Seeing this screen I found out that you have to use the commandline of VS instead of the builtin windows one.

# re: Create Strong Named Assemblies - The Easy Way 9/17/2007 9:16 AM vijay
where shold i get this signer.exe. coulsd you please provide me the location.
thanks in advance .
vijay

# re: Create Strong Named Assemblies - The Easy Way 9/25/2007 7:37 AM markl
My guess he removed it due the problems others have found. I would like to try this even though others have encountered problems. Can someone send it to me or tell me how to get it?

Mark.Lauritsen@idera.com

# re: Create Strong Named Assemblies - The Easy Way 9/26/2007 4:51 AM markl
Ah, I found the link to the program. In the first paragraph where it says "I have created Signer", "Signer" is the link to the download page.

# re: Create Strong Named Assemblies - The Easy Way 11/25/2007 3:40 AM Zachi Sharon
Hi,

I tried to add signing to MagicLocalLibrary.dll (unsigned assmebly):
signer.exe -k MagicLocalLibrary.snk -a .\bin\MagicLocalLibrary.dll -outdir .\tmp2

And got an error:
Output directory does not exist. Creating it now: F:\Projects\CosmoCom\Universe\Source\CCEmailClient\tmp2
Strong naming .\bin\MagicLocalLibrary.dll ...
An error occured while processing file .\bin\MagicLocalLibrary.dll: The assembly name was null or empty for type ##, parsed line: + "n=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e0"

Can you please help?

Thanks,

Zachi.

# re: Create Strong Named Assemblies - The Easy Way 11/25/2007 7:23 AM Alois Kraus
hi Zachi,

it seems that you tried to sign an Interop assembly. There is some bug lurking inside the signer source code but the servers did crash and I had already started a new version which should get a better parser. But unfortunately I did not have so much time to finish it.
A workaround would be for assemblies that have no dependencied to other unsigned assemblies
ildasm yourdll.dll /out=yourdll.il
ilasm /DLL /key=c:\key.snk yourdll.dll

Sorry for the inconvinience.

Yours,
Alois Kraus




# re: Create Strong Named Assemblies - The Easy Way 1/2/2008 7:33 PM Bao
Hi Alois, your tool is great, but have you overcome the limitation to make it be able to sign assemblies with unmanaged code? I really need it!

# re: Create Strong Named Assemblies - The Easy Way 1/26/2008 10:46 PM Achintya
A great tool! thank you so much!

# re: Create Strong Named Assemblies - The Easy Way 8/18/2008 7:05 PM shmera
Looks like a great, but can't get it working.
Generated a key-file as stated and tried the tool:

Signer -k C:\test.snk -outdir C:\Signer -a Test.exe which gave me the following error:

Execute of corflags.exe failed

Execute of ildasm.exe /? failed
An unexpected processing error did occur: System.NullReferenceException: Object
reference not set to an instance of an object.
at Signer.Executor.GetInvalidCommands()
at Signer.Program.Execute()
at Signer.Program.Main(String[] args)


This problem is discussed above.. but i didnt get the solution.. what exactly i have to do? any clear idea?


# re: Create Strong Named Assemblies - The Easy Way 11/20/2008 12:11 AM butters
shmera, as suggested previously, run the signer tool exactly as you did, but from the VS2005 command prompt. There's a link in the VS2005 program group on your start menu.

# re: Create Strong Named Assemblies - The Easy Way 11/20/2008 12:14 AM butters
This worked perfectly, many thanks Alois. Sending plenty of good karma your way :)

# re: Create Strong Named Assemblies - The Easy Way 5/24/2009 6:31 PM Pavan kumar

This worked perfectly. Thanks a lot Sir.

--
Pavan kumar

# re: Create Strong Named Assemblies - The Easy Way 6/16/2009 3:09 AM Mark Townsend
This looks like a tool I am looking for. However, I am confused, can it use password PFX files for the key? If so how can I give the name of the pfx file and the password?

Thanks


# re: Create Strong Named Assemblies - The Easy Way 9/24/2009 11:32 AM Ramesh Konduri
Thanks Alois,

This tool helped me a lot.

# re: Create Strong Named Assemblies - The Easy Way 1/14/2010 12:22 PM Erick
Could not load file or assembly 'PDFBox-0.7.3, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Im getting this error on my project, when i tried to sign this assambley it crashes
im using this
signer -k pdfkey.snk -outdir .\ok -a *.dll

# re: Create Strong Named Assemblies - The Easy Way 2/21/2010 7:07 PM J-d
Great tool!

Is there an update on signing interop assemblies?

# re: Create Strong Named Assemblies - The Easy Way 5/2/2010 5:26 PM Khushboo Gupta
Hi,
I tried creating stron name key
using sn-k test.snk
The key was created , but when i tried the command ilasm test.dll /DLL /key=test.snk

I got an error that ***Failure***
Could not open test.dll.

I have executed all the above command in the folder where test.dll is located.

Please help...
Thanks,
Samy

# re: Create Strong Named Assemblies - The Easy Way 5/30/2010 1:22 AM Maurice
Excellent tool!
I had my manual batch file to create the signed assembly and got some errors with the PublicKeyToken=null which where greatly solved with your tool!

Thanks a lot!

# re: Create Strong Named Assemblies - The Easy Way 3/13/2011 9:49 PM Powertoy
Hi, This is really great tool and It helped me a lot. Now the only thing remaining is, signing the assembly if it contains unmanaged code. Currently it doesn't sign the assembly if it contains unmanaged code. I have checked phoenix project. Any luck on providing Signer tool supporting signing unmanaged assembly by using phoenix project?

It would be really great to sign an assembly (containing unmanaged code).

Thanks..

# re: Create Strong Named Assemblies - The Easy Way 3/22/2011 1:44 AM Powertoy
This utility developed by you really helps. Thanks a lot for sharing such a useful code base.

Currently I am working on a project where I have to sign multiple not signed assemblies. This utility works but it it doesn't emit InternalsVisibleTo attribute.

One of my assembly uses InternalsVisibleTo but when I run this utility and check that assembly, that attribute is no longer applied to it.

Also I have checked the binary and the code base. They are out of sync.

Would you please help me if you have a solution for this problem?

Many Thanks in advance.

# re: Create Strong Named Assemblies - The Easy Way 3/22/2011 7:53 AM Alois Kraus
I knew that someday somebody will ask for the InternalsVisibleToAttribute. Unfortunately the code got lost during a server upgrade some years ago and I only have an old version of the code at hand. Currently I do not have time to add this feature. Besides this I would use today Mono.Cecil for decompilation which should be easier. Perhaps I will add it to the ApiChange tool someday.

Yours,
Alois Kraus


# re: Create Strong Named Assemblies - The Easy Way 3/23/2011 7:10 PM Powertoy
Hi Kraus,

Thanks for prompt reply. I have regenerated the code from the binary by using reflector and modified the code so that it emits InternalsVisibleTo correctly.

Now my only problem is, I want to sign unmanaged dll.

I have checked phoenix project. Any luck on providing Signer tool supporting signing unmanaged assembly by using phoenix project?

It would be really great to sign an assembly (containing unmanaged code).

Thanks..

# re: Create Strong Named Assemblies - The Easy Way 6/28/2011 6:32 AM core24
I needed to strongly name some .net 4 assemblies, but the current binaries only work with a .net 2.0 runtime.

So I compiled the source against .net 4 and it works for the most part, but ran into an issue with a DLL that barfed in ILUpdater trying to parse out the assembly name on line 498 against this IL code:

"marshal( custom ("System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler, CustomMarshalers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",""))"

Looks like ildasm.exe in .net 4 uses double quotes to delimit the strong name string, so I cahnged line 437 to:

if (c == '\'' || c == '"')

# re: Create Strong Named Assemblies - The Easy Way 7/14/2011 12:19 AM Staffan Eketorp
I can see that the current source code at CodePlex doesn't match the released .exe. Any possiblity of changing this so that the source code is on par?

Thanks!

# re: Create Strong Named Assemblies - The Easy Way 11/1/2011 6:24 PM Rami
Hi.

Thank you for Signer.exe v1.0.

I have created work items on the project page with some of the issues that I've encountered, along with others that have reported them on this page.

http://signer.codeplex.com/workitem/list/basic

I believe creating and contributing to individual work items on the project page will allow us to better manage the issues rather than adding comments to this post.

# re: Create Strong Named Assemblies - The Easy Way 5/17/2012 8:21 AM Abe Miessler
Is it possible to specify the framework you want the generated signed assembly to be built in?

Post A Comment
Title:
Name:
Email:
Comment:
Verification: