views:

1198

answers:

3

This may be a daft question as I can see the security reason for it to happen the way it does...

I have a licensing c# project, this has a class which has a method which generates my license keys. I have made this method private as I do not want anybody else to be able to call my method for obvious reasons

The next thing I want to do is to have my user interface, which is in another c# project which is referencing the licensing dll to be the only other 'thing' which can access this method outside of itself, is this possible or do i need to move it into the same project so that it all compiles to the same dll and I can access its members?

LicensingProject
-LicensingClass
--Private MethodX (GeneratesLicenseKeys)

LicensingProject.UI
-LicensingUiClass
--I want to be able to be the only class to be able to access MethodX

There is a reason why the license Key Generator is not just in the UI, that is because the licensing works by generating a hash on itself and compares it to the one generated by the License Generator.

I would prefer not to all compile to the dll as my end users do not need the UI code.

I know that by common sense a private method, is just that. I am stumped.

Thanks, Phill

A: 

public, private, ... stuff are just enforced by the compiler. You can use reflection to access them pretty easily (assuming the code has required permissions, which is a reasonable assumption as he has complete control on the machine). Don't rely on that assuming nobody can call it.

Mehrdad Afshari
Not true; they are enforced by both reflection and the CLI too - simply that often you are running with full-trust, so you don't notice it... but this should not be assumed
Marc Gravell
(as you note on Jon's post - ReflectionPermission)
Marc Gravell
@Marc: I don't think CLR enforces anything for calling a private method. I updated my answer to reflect the controversy. I'm not 100% sure about what I say. I'll be happy to be corrected.
Mehrdad Afshari
based on writing some code via Reflection.Emit that uses (at runtime) neither reflection nor the C# compiler, I'm fairly sure it does... I'll try to investigate, though.
Marc Gravell
I've added evidence of this in a reply
Marc Gravell
+5  A: 

You could make it an internal method, and use InternalsVisibleToAttribute to give LicensingProject.UI extra access to LicensingProject.

Merhdad's point about enforcement is right and wrong at the same time. If you don't have ReflectionPermission, the CLR will stop you from calling things you shouldn't - but if you're using reflection from a fully trusted assembly, you can call anything. You should assume that a potential hacker is able to run a fully trusted assembly on his own machine :)

None of this will stop someone from using Reflector to decompile your code. In other words, making it private isn't really adding a significant amount of security to your licensing scheme. If anyone actually puts any effort into breaking it, they'll probably be able to.

Jon Skeet
I don't think CLR will stop you from calling private methods. Certainly, if the method has CAS demands that you can't satisfy, you won't be able to call it. As long as you have ReflectionPermission, I think you can call any private method (that doesn't require any other permissions). Correct me if I'm wrong...
Mehrdad Afshari
ReflectionPermission is what I was thinking of. Without that, you can still call public members by reflection. But yes, it's not actually full trust that's required - will edit.
Jon Skeet
Thank you for the answers to both Jon and Mehrdad.
Phill Duffy
+1  A: 

This is really a comment, in response to Mehrdad's point about the runtime not performing access checks; here, you can see the JIT (it transpires) performing the access check - not reflection, and not the C# compiler.

To fix the code, make Foo.Bar public. Interestingly, it also verifies that Foo is accessible - so make Foo internal to see more fireworks:

using System;
using System.Reflection;
using System.Reflection.Emit;
static class Program {
    static void Main() {
        MethodInfo bar = typeof(Foo).GetMethod("Bar",
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        var method = new DynamicMethod("FooBar", null, new[] {typeof(Foo)});
        var il = method.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.EmitCall(OpCodes.Callvirt, bar, null);
        il.Emit(OpCodes.Ret);

        Action<Foo> action = (Action<Foo>) method.CreateDelegate(typeof(Action<Foo>));
        Foo foo = new Foo();
        Console.WriteLine("Created method etc");
        action(foo); // MethodAccessException
    }
}

public class Foo {
    private void Bar() {
        Console.WriteLine("hi");
    }
}
Marc Gravell
Interesting indeed. +1
Mehrdad Afshari
I'll be honest, I understand not a lot of that! I will try and do my best on understanding it though. I like it when people go deeper than just the initial question , +1 to SO and its users!
Phill Duffy
@Phill - too much Reflection.Emit can destroy the mind...
Marc Gravell