6

An earlier question of mine, Prevent package from being opened in a notebook interface, never received an answer, but Albert Retey's comments did lead me to an entirely different solution.

To secure my Mathematica code for distribution to a client I now plan to wrap encoded Mathematica code in C# code and compile it to a DLL. The client will then call the DLL from their .NET application with specific methods that will call my proprietary Mathematica functions. My compiled code will handle all .NET/Link operations.

Wrapping encoded code in a DLL may seem like overkill (well I still tie double knots in my shoelaces). I just want to make the code as secure as possible and as I have to do the compiling on my client's Window's machine (I use Mac) I want to do everything to keep it from curious eyes.

I've written a package and encoded it. I've tested the package in the client environment by loading the encoded package file from a notebook interface. This works fine.

I've done a second test. In a notebook, I copied the encoded text and pasted it into a cell and assigned it to a variable, something like:

myEncodedString = "(*!1N!*)mcm
j<hTJue'P+lKh]7t>X#r/N5>m^c0Q j,fdE~0y@X>TkncC'AMluD1_R3,0?vQR0(n|p08B
D\O%!1o3t~`#0VL...a bunch more encoded text..."

Following this I tried:

Get[myEncodedString]

This didn't work. I revisited what I needed to do and realized I could make it work by using the form Get[stream] and tried the following:

Get@StringToStream[myEncodedString]

This gave me the following dialogue box:

enter image description here

Selecting "Yes" ran the code and made all of its function definitions available.

Now I tried to do the same thing from C# via .NET/Link, which did not work. I think it didn't work because I need some way to insert escapes in the encoded text.

Does anyone have an idea of how to do this or more generally how to get this to work?

Jagra
  • 14,343
  • 1
  • 39
  • 81

1 Answers1

4

There is an easy way to achieve what you want. First, let's load some sample package, encode it and re-import it as string:

file = FileNames["Collatz.m", {$InstallationDirectory}, Infinity];
encoded = ToFileName[$TemporaryDirectory, "encoded"];
Encode[First[file], encoded];
encCode = Import[encoded, "Text"]

(* mcmM$RqUiqylb8ORSH!A>J.... *)

After that it is as easy as

ImportString[encCode, "Package"]

and you can test by calling ??Collatz that the package was loaded successfully.

halirutan
  • 112,764
  • 7
  • 263
  • 474
  • Let me make certain, I follow your solution and perhaps clarify it for others. Using something like myEncodedString=ImportString[encCode, "Package"] gives me a proper string equivalent of the encoded package. Next I can copy that string into the C# code with the Get@StringToStream[myEncodedString] (because the Get[] will still need a stream?) or will myEncodedString execute directly? I ask because I don't have access to a Windows machine to test the C# NET/Link over the weekend. – Jagra May 10 '14 at 11:59
  • @Jagra ImportString[encCode,"Package"] is equivalent to using Get on a file containing the encoded package. Therefore, ImportString[encCode, "Package"] evaluates the package code and after this call your function definitions are available (like Collatz[..] here). It doesn't give you a string. – halirutan May 10 '14 at 12:06
  • OK, if I follow, this should get me past the dialogue box when running this from a notebook, but I don't yet see a clear way to get this to run from the C# Net/Link world. As you pointed out in your answer to Prevent package from being opened in a notebook interface?, I don't want a package (encoded or not) file sitting around somewhere accessible to spelunking. Thoughts? Explanation? Is your WolframLibrary idea, from the referenced answer, a better approach? – – Jagra May 10 '14 at 12:36
  • You can translate the WolframLibrary idea directly into NETLink. The code I used to inject the encoded package into the C code and load it from within the library call can be done in almost exactly the same way in NETLink. You will find everything you need in this tutorial. – halirutan May 10 '14 at 17:01
  • If you want to discuss some details then we could meet in [chat]. I guess I have some time in about 2 hours (7 pm UTC). – halirutan May 10 '14 at 17:03
  • The risk of having the file on disk and available for examination is significantly lessened by specifying a key when Encodeing it. You then only need to keep the key in the .NET library, not the entire package. – Oleksandr R. May 10 '14 at 17:23
  • @OleksandrR. The overall goal is to compile the string of the package code directly into the library like asked here. This question here was AFAIK only a sub-question on the way to this goal. What I suggest in the other answer is to compile the package code to have a further level of obfuscation because an attacker would need to (1) decompile the library to extract the package-string, (2) crack Encode to make it plain text again. Btw, do you have a mail-adress? Would you send me a mail (you'll find my address) which I can answer? – halirutan May 10 '14 at 18:08
  • I emailed you. :) – Oleksandr R. May 10 '14 at 18:22
  • Thanks for the offer to chat, but I think I've got a way forward at this point (I might ping you later:-). I'll report back on my progress. Again, a great idea. Actually two great ideas. – Jagra May 10 '14 at 18:37