I was trying to find a way to limit the execution of some public methods of a class in an assembly from assemblies which I have not written.
Let me first explain you the problem I was facing, then I will share the approaches I had tried or thought, and finally the ODD WAY I have figured to overcome the problem I was facing.
Problem:
I have a helper class, say CryptoHelper, in one of my assemblies to encrypt/decrypt the information. The class contains all the necessary information to encrypt/decrypt the string data passed to its public methods namely Encrypt and Decrypt. The user of the class simply instantiates it, sets the encryption algorithm provider and uses the methods
Scope of class is Public because I have to use it in other assemblies for encryption/decryption. I am happy with the helper class, as it is helping me very well in encrypting/decrypting the text passed to it. The problem I see here is that I have stored encrypted information in database using the class and the assembly deployed at client’s end can be used by some knowledgeable person to decrypt the information stored using the class in the assembly.
I want to stop the use of class from code that I have not written, or more specifically, the code that is not part of the project for which the assembly is deployed.
Approaches:
Following are the approaches I thought, and the reason why I have rejected them.
- Obfuscate the code: Believe me, I seriously thought about obfuscating the code. This was the first idea that struck into my mind, but the very next minute I rejected the idea because I love the call stack information in the exception trace log. I don’t want to get lost into translation.
- Use System.Runtime.CompilerServices.InternalsVisibleToAttribute: I don’t have any explanation to why I have rejected the option of using the InternalsVisibleToAttribute [See MSDN Library], but I have a story to tell you about how hard luck forces one to find the ODD WAY out. I was happy to find the attribute and changed the class scope from public to friend. I used the attribute in AssemblyInfo.vb file specifying the friend assembly name and friend assembly Public Key Token. Upon recompiling the project … I was shocked to see the compilation errors in the code that was using the class. The code that was consuming the class stopped recognizing the class. I tried again and again, following the instructions as specified in the MSDN documentation but it didn’t worked for me. I googled again and again to find the reason of failure, and after quite effort I have found the answer to my problem. Tim Ng, Microsoft Visual Basic Team member, had a bad news for me. According to his blog entry, the InternalsVisibleToAttribute doesn’t work with Visual Basic 2005 compiler.
ODD WAY:
The ODD WAY I have found is to use the assembly signing information to check if the calling code is signed with same key as that of the assembly which holds my CryptoHelper class. In Encrypt and Decrypt methods I have added a conditional statement which checks if the Calling Assembly’s Public Key Token Matches with the Public Key Token of Executing Assembly. Look at the following code snippet to get better understanding of what I am saying.
Public Function Decrypt(ByVal strTextToDecrypt As String) As String‘……….If System.Reflection.Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken().Equals( _System.Reflection.Assembly.GetCallingAssembly().GetName().GetPublicKeyToken()) = True Then‘Code to decrypt the textElseThrow New NotSupportedException(“You are not allowed to use this method”)End IfReturn strDecryptedTextEnd FunctionThis is my ODD WAY out to fix the issue.
One quick improvement to the solution is to throw the exception from the class constructor using the logic mentioned above in the code.
I will look into the other improvements as well, but for now, I am going to end this post here.
Happy coding.
Jawwad Alam