Prevent Reflection and Disassembly of Silverlight Class Libary Code

Over the weekend, I began to think about how to better protect proprietary algorithms and other sensitive code in a Silverlight application, keeping the assembly away from prying, snooping eyes. I decided the best way would be to keep the code in memory and never have it committed to the hard drive. A little research and a little coding and badda bing (er, badda google?).

The solution turns out to be rather simple. You need four projects: the Silverlight app, the web app, the contract (interface) and the implementation Silverlight class libraries. The Silverlight app references the contract library which pulls it into the XAP. The implementation library references the contract library to implement the interface, of course. And the web app does its thing, supplying the XAP file to the browser and most importantly supplying the protected bits via a stream that presumably is protected by SSL, authentication and authorization mechanisms, items I've conveniently left out of this post and the sample code for brevity.

Start with the AppManifest.xaml (in Dinorythm.xap)
Note that the manifest contains only the Silverlight app and the contract class library along with the other assemblies required for the Silverlight Navigation Application (find what you need at Scott Guthrie's informative Silverlight 4 Released blog post).

<Deployment 
    xmlns="http://schemas.microsoft.com/client/2007/deployment" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    EntryPointAssembly="Dinorythm" 
    EntryPointType="Dinorythm.App" 
    RuntimeVersion="4.0.50401.0">
  <Deployment.Parts>
    <AssemblyPart x:Name="Dinorythm" Source="Dinorythm.dll" />
    <AssemblyPart x:Name="DinoContracts" Source="DinoContracts.dll" />
    <AssemblyPart x:Name="System.ComponentModel.DataAnnotations" Source="System.ComponentModel.DataAnnotations.dll" />
    <AssemblyPart x:Name="System.ServiceModel.DomainServices.Client" Source="System.ServiceModel.DomainServices.Client.dll" />
    <AssemblyPart x:Name="System.ServiceModel.DomainServices.Client.Web" Source="System.ServiceModel.DomainServices.Client.Web.dll" />
    <AssemblyPart x:Name="System.ServiceModel.Web.Extensions" Source="System.ServiceModel.Web.Extensions.dll" />
    <AssemblyPart x:Name="System.Windows.Controls" Source="System.Windows.Controls.dll" />
    <AssemblyPart x:Name="System.Windows.Controls.Navigation" Source="System.Windows.Controls.Navigation.dll" />
  </Deployment.Parts>
</Deployment>

 

DinoContracts a Silverlight 4 Class Library (in Dinorythm.xap).
To any nosy disassembler looking for the secret sauce code, all they will get is the interface and perhaps a few domain classes if you need them.

namespace DinoContracts
{
  public interface IMySecretCode
  {
    string DoSecretWork(string input);
  }
}

 

SecretAlgorithms a Silverlight 4 Class Library (NOT in Dinorythm.xap)
This library has a project reference to DinoContracts and copies it's output to the Dynorythm.Web/App_Data folder.

namespace SecretAlgorithms
{
  public class MySecretCode : IMySecretCode
  {
    public string DoSecretWork(string input)
    {
      return "results of my secret code";
    }
  }
}

 

Dinorythm.Web an ASP.NET MVC 2 project
Obviously this code is not production ready. You need some security here, but what you see here will get you the result you seek. Securing this action method might be a good topic for another blog post.

namespace Dinorythm.Web.Controllers
{
  [HandleError]
  public class HomeController : Controller
  {
    //...other code removed for brevity

    public FileContentResult Secret()
    {
      string ctype = "application/octet-stream";
      string fileName = "SecretAlgorithms.dll";
      byte[] dll = GetFile(fileName);
      return File(dll, ctype, fileName);
    }

    byte[] GetFile(string fileName)
    {
      string path = HostingEnvironment.MapPath(@"~/App_Data/" + fileName);
      byte[] bytes = System.IO.File.ReadAllBytes(path);
      return bytes;
    }
  }
}

 

Dinorythm a Silverlight 4 Navigation Application
This app has a project reference to DinoContracts but knows nothing about the SecretAlgorithms project. The secret code in this demo won't win any awards but it might help you conceive (and me to remember) of how to get the job done with your real intellectual property.

namespace Dinorythm
{
  public partial class About : Page
  {
    public About()
    {
      InitializeComponent();
    }

    // Executes when the user navigates to this page.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
      WebClient down = new WebClient();
      down.OpenReadCompleted += new OpenReadCompletedEventHandler(down_OpenReadCompleted);
      Uri location = new Uri(System.Windows.Application.Current.Host.Source, @"../Home/Secret");
      down.OpenReadAsync(location);
    }

    void down_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
      AssemblyPart part = new AssemblyPart();
      Assembly asm = part.Load(e.Result);
      IMySecretCode secret = (IMySecretCode)asm.CreateInstance("SecretAlgorithms.MySecretCode");

      if (secret != null)
        this.ContentText.Text = secret.DoSecretWork("help me");
      else
        this.ContentText.Text = "was null";
    }
  }
}

Help credits go to Tim Heuer for some comparison with cached assemblies and to the practical help from a Silverlight Tip of the Day.

A Note About Security: I am not a self-proclaimed security expert. I'm sure there are ways to defeat this approach, but I suspect that doing so would be more trouble than it would be worth. But certainly this would be more efficient than simple or even complex obfuscation. Then again one could obfuscate and then dynamically download and instantiate in memory. That ought to really throw a would be intellectual property thief for a real loop. (Also note, I've never tried obfuscation in a Silverlight class library, so perhaps it's not even possible. Hmm... Another research and blog topic.)

If you find this code useful, I'd love to hear from you. Download Dinorythm.zip (313.34 KB) here.

Why I Would Like to Work for Warren Buffett

In his annual letter to shareholders, Warren Buffett wrote (emphasis added):

“We tend to let our many subsidiaries operate on their own, without our supervising and monitoring them to any degree. That means we are sometimes late in spotting management problems and that both operating and capital decisions are occasionally made with which Charlie and I would have disagreed had we been consulted. Most of our managers, however, use the independence we grant them magnificently, rewarding our confidence by maintaining an owneroriented attitude that is invaluable and too seldom found in huge organizations. We would rather suffer the visible costs of a few bad decisions than incur the many invisible costs that come from decisions made too slowly – or not at all – because of a stifling bureaucracy.

There are times when working in an enterprise can be frustrating because there are individuals who deliberately and regularly hinder your work while hiding behind the plausible deniability and comfortable safety of that stifling bureaucracy of which Warren Buffett so sagely speaks.

The question is what to do when you find yourself in that situation. There can be only three answers, I believe. Either you succeed in spite of the efforts of well seasoned bureaucrats and hope that attrition wins the day or you fail while trying or even give up somewhere along the line, resigning yourself to failure. The third alternative is that you find another ball field and another team on which to play and never look back.

Which one would you choose?

Critical Distinction Between IEnumerable and IQueryable in LINQ to SQL or EF

I rarely just parrot-link another blogger’s post, but I’m going to make an exception here to give props to Chris Sells and his excellent “The Performance Implications of IEnumerable vs. IQueryable.”

Chris, the venerated Microsoft Legend, walks us through a great example of where the use of IEnumerable vs IQueryable can get you into trouble. With a simple swap, Chris goes from returning every row in a table to a simple count(*).

The critical thing to learn is that IQueryable is “composable” meaning that you can make one from another before executing the final “outer” query and having the composed expression parsed and executed.

One additional note, however, is the gotcha that can bite you on the keester if you’re not careful. With an IQueryable dependent upon a data context, don’t lose the context or you’ll end up with:

ObjectDisposedException: Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.'.

So watch out for the dangling context. :)

Third Party UI Libraries Can Be Overkill

The question of the value of third party UI libraries has often come up in my career. At one time I was an eager advocate of using a comprehensive UI library. Now my attitude is a bit more pragmatic.

Third party UI libraries are sometimes a boon and sometimes a bane. Even for well seasoned UI frameworks. UI libraries for web applications tend to be particularly troublesome because they so often have a clumsy, heavyweight configuration and API that end up requiring more time to use than they save while the vendors race to win the feature count contest.

For some years, the trend seemed to lean toward the use of UI libraries because building a UI by hand was hard regardless of whether you were working with spaghetti script or with Win32 and MFC. Now Microsoft's toolset supports a much richer set of UI paradigms making the delivery of a great UI much easier right out of the box. The trend seems to be gravitating away from reliance on third party controls toward a more simplified user interface style with a more elegant framework relying more on convention than a feature bloated configuration and black box API.

One area where UI libraries seem to continue to do well, in my view of course, is with Silverlight and WPF (XAML) applications. These UI frameworks and their supporting third party UI control sets seem to have been made for each other. Both rely heavily on the powerful UI declarative language XAML. The rich user interfaces that can be spun up using Silverlight or WPF can be intoxicating.

Ultimately, we need to use UI libraries judiciously, being careful not to overuse them where requirements and the effort needed to learn and configure them are not warranted. One could argue that the limited way in which many third party controls are used in a variety of applications provide us with a bountiful set of examples of the gratuitous overuse of these libraries. Sometimes all you need is a good closet and the kitchen sink that comes with that room builder toolkit is just plain old overkill.