When you sign an assembly with a strong name based on the private key you create, this has the following advantages:
- A strong name ensures that the assembly identifier is unique by adding a public key token and digital signature to the assembly.
- A strong name can be mapped to a public key to prove that the assembly comes from the publisher with this public key and only with this publisher.
- A strong name provides reliable integrity checking. Passing the .NET Framework security checks ensures that the contents of the assembly have not been modified since the last assembly.
Can I use a strong name to verify the author of the assembly?
Yes, as discussed above, a strong name can verify the author of the assembly last . But he does not check the original author. If an attacker replaces your strong build name, all you can verify is that you were not the last author of the assembly. If he removes the strong name, then no author check can be performed at all.
To what extent can a strong named assembly be verified to avoid fake?
The following C # code verifies that the attacker did not fake the public key token that was written to your assembly when you used the strong name. He does not avoid fakes, but can detect some types of fakes. The method below takes an array of bytes containing the public key token, and compares it with the actual build token. Note that in order for this method to be effective, your selection obfuscator must encrypt the string containing your public key token, and only decrypt it on the fly as it is used. And also keep in mind that you need FullTrust permission for this code to work, because it uses reflection under the hood.
// Check that public key token matches what expected. private static bool IsPublicTokenOkay_Check(byte [] tokenExpected) { // Retrieve token from current assembly byte [] tokenCurrent = Assembly.GetExecutingAssembly().GetName().GetPublicKeyToken(); // Check that lengths match if (tokenExpected.Length == tokenCurrent.Length) { // Check that token contents match for (int i = 0; i < tokenCurrent.Length; i++) if (tokenExpected[i] != tokenCurrent[i]) return false; } else { return false; } return true; }
While you are running a version of the .NET Framework prior to .NET 3.5 SP1, you can also force the strong name signature to be verified if the strong name was deleted by an attacker or the strong name verification was disabled in the registry. The following code demonstrates a call in the static method of another class called NativeMethods. This will check.
// Check that this assembly has a strong name. private bool IsStrongNameValid_Check() { byte wasVerified = Convert.ToByte(false); byte forceVerification = Convert.ToByte(true); string assemblyName = AppDomain.CurrentDomain.BaseDirectory + AppDomain.CurrentDomain.FriendlyName; return NativeMethods.CheckSignature(assemblyName, forceVerification, ref wasVerified); }
Actual signature verification is done using P / Invoke, as shown below. Using the StrongNameSignatureVerificationEx API is pretty tricky - for a decent explanation, see this blog post .
// P/Invoke to check various security settings // Using byte for arguments rather than bool, // because bool won't work on 64-bit Windows! [DllImport("mscoree.dll", CharSet=CharSet.Unicode)] private static extern bool StrongNameSignatureVerificationEx(string wszFilePath, byte fForceVerification, ref byte pfWasVerified); // Private constructor because this type has no non-static members private NativeMethods() { } public static bool CheckSignature(string assemblyName, byte forceVerification, ref byte wasVerified) { return StrongNameSignatureVerificationEx(assemblyName, forceVerification, ref wasVerified ); }
Please note that this will not work by default for applications using .NET 3.5 SP1 or higher, which has the function to disable this function for your application by adding a parameter to its configuration file. But, of course, any attacker with read and write access to this configuration file can reverse your decision.