Posterous theme by Cory Watilo

Checking an assembly for a strong name and a specific public key

I’m currently writing some code where I needed to check if a, dynamically, loaded assembly had a strong name and was signed using a specific (in this case, the same as the host application) public key.


At first I could only figure out how to check the public key but I was unable to find a way to check for a valid strong name as well. That is, until I dig some digging and found out that there was no managed code to perform the check. but instead I had to turn over to interop to get the job done.


It wasn’t until I found the .NET Security Blog that I found out that there was an unmanaged function called StrongNameSignatureVerificationEx, in the mscoree.dll file, which would do the trick. So I wrote a couple of extension methods for the Assembly class to help check for a strong name, a specific public key and a method which performed both calls for me.


1:  using System.Linq;
2:  using System.Reflection;
3:  using System.Runtime.InteropServices;
4:   
5:  /// <summary>
6:  /// Adds functionality to the <see cref="Assembly"/> class, to check for
7:  /// a valid strong name and for a specific public key.
8:  /// </summary>
9:  public static class AssemblyExtensions
10:  {
11:      [DllImport("mscoree.dll", CharSet = CharSet.Unicode)]
12:      private static extern bool StrongNameSignatureVerificationEx(
13:          string filePath,
14:          bool forceVerification,
15:          ref bool wasVerified
16:      );
17:   
18:      /// <summary>
19:      /// Checks if the <see cref="Assembly"/> has a strong name and is
20:      /// signed with the same public key as the executing assembly.
21:      /// </summary>
22:      /// <param name="target">The <see cref="Assembly"/> to check.</param>
23:      /// <returns>
24:      /// true if the assembly contained the public key; otherwise false.
25:      /// </returns>
26:      public static bool IsTrusted(this Assembly target)
27:      {
28:          byte[] publicKey =
29:              Assembly.GetExecutingAssembly().GetName().GetPublicKey();
30:   
31:          return IsTrusted(target, publicKey);
32:      }
33:   
34:      /// <summary>
35:      /// Checks if the <see cref="Assembly"/> has a strong name and is signed
36:      /// with the provided public key.
37:      /// </summary>
38:      /// <param name="target">The <see cref="Assembly"/> to check.</param>
39:      /// <param name="publicKey">The public key to check for.</param>
40:      /// <returns>
41:      /// true if the assembly contained the public key; otherwise false.
42:      /// </returns>
43:      public static bool IsTrusted(this Assembly target, byte[] publicKey)
44:      {
45:          return IsStrongNamed(target) && IsSignedWith(target, publicKey);
46:      }
47:   
48:      /// <summary>
49:      /// Checks if the <see cref="Assembly"/> is signed with the provided
50:      /// public key.
51:      /// </summary>
52:      /// <param name="target">The <see cref="Assembly"/> to check.</param>
53:      /// <param name="publicKey">The public key to check for.</param>
54:      /// <returns>
55:      /// true if the assembly has a strong name; otherwise false.
56:      /// </returns>
57:      public static bool IsSignedWith(this Assembly target, byte[] publicKey)
58:      {
59:          if (publicKey != null)
60:          {
61:              if (target.GetName().GetPublicKey().SequenceEqual(publicKey))
62:              {
63:                  return true;
64:              }
65:          }
66:   
67:          return false;
68:      }
69:   
70:      /// <summary>
71:      /// Checks if the <see cref="Assembly"/> has been signed with
72:      /// a strong name.
73:      /// </summary>
74:      /// <param name="target">The <see cref="Assembly"/> to check.</param>
75:      /// <returns>
76:      /// true if the assembly has a strong name; otherwise false.
77:      /// </returns>
78:      public static bool IsStrongNamed(this Assembly target)
79:      {
80:          bool notForced = false;
81:          bool verified =
82:              StrongNameSignatureVerificationEx(target.Location,
83:              false, ref notForced);
84:   
85:          return verified;
86:      }
87:  }

Once you have added the extensions methods to your project, you can, for example, check if a loaded assembly is strong named and is signed by the same public key as the hosting application by calling the IsTrusted method


1:  Assembly file =
2:      Assembly.LoadFrom(@"SomeAssembly.dll");
3:   
4:  if (file.IsTrusted())
5:  {
6:      // do some magic
7:  }

If you need to check for another public key just use the overload and pass in the key in question. The IsStrongNamed method can be called to check for a strong name, and the IsSignedWith method will only check for the specified public key.


The fill source code can be downloaded from my codeplex page.