Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make InternalsVisibleTo attribute work by signing a public token key safely?

I am trying to expose some internals to my unit test project by using:

[assembly: InternalsVisibleTo("MyTest")]

But I am getting the error:

Error 1 Friend assembly reference MyTest' is invalid. Strong-name signed assemblies must specify a public key in their InternalsVisibleTo declarations. .../MyClass.cs...

When I assign a PublicTokenKey manually:

[assembly: InternalsVisibleTo("MyTest, PublicKeyToken=XxxxxYysakf")]

The solution builds without any error.

  1. Why do I need to include a public key token?
  2. I am not sure if I will break something in production by including the public key token.

So, what is the best and safest way to assign an public key to my Test project?

like image 257
pencilCake Avatar asked Aug 25 '11 13:08

pencilCake


People also ask

How do I find my public key for InternalsVisibleTo?

In the "Solution explorer" click on your project assembly name, and then head to "Tools > Get PublicKey".

What's the usage of InternalsVisibleTo attribute?

From the documentation, the assembly-level InternalsVisibleTo attribute: Specifies that all nonpublic types in an assembly are visible to another assembly. This attribute was introduced in C# 2.0, and allows you to specify other assemblies that can see all types and members marked “internal”.

Which of the following attributes is required to identify one or more friend assemblies for a given assembly?

You can use the InternalsVisibleToAttribute attribute to identify one or more friend assemblies for a given assembly.


1 Answers

I am surprised that PublicKeyToken even works - on my machine it forces me to use PublicKey

  1. The reason that you need a public key token is because strongly-named assemblies can be put into the GAC - which has high trust. It would be a security hole if any assembly called 'MyTest' (that is potentially untrusted - e.g. a control in the browser) could call into the internals of a GACed assembly; it wants the public key to prevent this type of hack.

  2. This shouldn't break anything in production - even if the assembly cannot be found. This attribute is used during compile-time and not runtime.

What is the safest way?

If you are really worried about it breaking production code, remove the attribute during release builds:

#if (DEBUG || TEST)
[assembly: InternalsVisibleTo("MyTest, PublicKeyToken=XxxxxYysakf")] 
#endif

If you have a few projects that need the public key token (and you have a single key pair, which you should) you could also define a file such as AssemblyInfo.global.cs and add it as a linked file to all your projects:

class KeyTokens
{
   public const string Global = ", PublicKeyToken=XxxxxYysakf";
}

This simplifies things to (especially if you need to use the PublicKey which is really long):

#if (DEBUG || TEST)
[assembly: InternalsVisibleTo("MyTest" + KeyTokens.Global)] 
[assembly: InternalsVisibleTo("HisTest" + KeyTokens.Global)] 
[assembly: InternalsVisibleTo("TheirTest" + KeyTokens.Global)] 
#endif
like image 132
Jonathan Dickinson Avatar answered Nov 01 '22 12:11

Jonathan Dickinson