51

If I want to make package-code completely unreadable, in a way that the end-user can only call my functions, but has no way to re-engineer my definitions, how would I do that?

I know I can use Encode to make scrambled code which, quoting the doc, cannot be converted back by any Mathematica function. But even with an encoded package, the user could look at the definitions of my functions. So I should add some attributes: Protected, ReadProtected, Locked.

Would that be enough? Has someone experience with this?

Additional question: How do I distribute this? In the Workbench one has to process all Documentation files and can then create a .zip or a .tgz from its package, but there are unencoded files used. Do I have to encode the files by a script or is there already a solution?

halirutan
  • 112,764
  • 7
  • 263
  • 474

3 Answers3

29

My suggestion is to use a combination of encryption, DumpSave (as noted in some answers / comments), and Locked / ReadProtected, which should give your code a reasonable level of security. You can't make things totally safe, in Mathematica or any other language. Using DumpSave however means that you should create a version of a package for each platform you want to support. But, if you really want to protect your code, this extra work does not seem that unreasonable.

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
19

Mathematica-Users.org says:

The basic idea is to include commands at the end of your package which set the attributes of your "secret" functions to be ReadProtected, and then Locked. The ReadProtected means no one can see the function definitions, and the Locked means no one can undo the ReadProtected attribute.

It is probably not a good idea to also set the attribute Protected, because with Locked also engaged, your users will not be able to SetOptions on your functions.

The package file is still human readable and offers no protection from prying eyes. Saving the notebook as a package file in ".mx" format with the attributes set as indicated, offers protection from peepers, since the mx file is not human readable, but this option has some issues, mentioned above.

An alternative is to encode the package file with the Encode routine. This encrypts the package file, such that it is no longer human readable, but because it is an ASCII text file it is more portable. There is an exception to this portability - Linux encodes files differently from OS X and Windows.

The Needs or Get commands can read in the Encoded package file (possibly requiring a password, if you set one) and decrypt it, and once the package is in memory, the Locked and ReadProtect attributes now protect the secrets in your code. Here we give an example of this. We first show a trivial package that is written in a notebook, and saved as "demo.nb", for example. Since it's a tiny package it might contain only one cell, whose Cell Properties are set to "Initialization Cell". Here we assume the "secret function" we want to protect is the function "encrypt".

See the link for more.

I believe you must accept making OS-specific packages. This is what I recall from a MathGroup thread that I cannot currently find.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • 1
    I think that the information about the OS dependency might not be correct anymore for version 8. If my memory isn't fooling me for earlier versions a package encoded on linux could be read everywhere but not the other way round. I think with 8 it should now work across all remaining platforms but can't find a reference nor test it right now. If one is after maximal security, distributing code in .mx format might be a better choice, as mentioned in Leonids answer. – Albert Retey Feb 11 '12 at 22:58
10

Something I once tried, but never really used, so no guarantees - but perhaps it is useful as a template:

LockContext[
  ctx_: ToString[
    Context[]]] := SetAttributes[Evaluate[ctx <> # & /@
     Names[ctx <> "*"]], {ReadProtected, Locked}]

This takes all defined symbols in ctx (default: current context) and applies some additional attributes to them. You could use this at the end of a package (respectively at the end of each - esp. the Private` context) to lock all relevant contexts and then save the encoded version (which is probably enough protection for the average honest user).

celtschk
  • 19,133
  • 1
  • 51
  • 106
Yves Klett
  • 15,383
  • 5
  • 57
  • 124
  • 2
    By assigning to Attributes you are deleting any attributes already set (like Flat or HoldAll), and thus potentially changing the semantics of the code. – celtschk Feb 10 '12 at 14:35
  • Correct! One should keep the already present attributes and add the others to that. Updated the answer to do so (but very probably still not foolproof - as mentioned above). – Yves Klett Feb 10 '12 at 16:23
  • Is there a reason why you don't simply use SetAttributes? – celtschk Feb 10 '12 at 16:27
  • nope... that was just some detritus I dregded up. Feel free to edit (you cannot make it worse, obviously). SetAttributes would be more elegant. – Yves Klett Feb 10 '12 at 16:34
  • 2
    Done. Note that I've used the fact that SetAttributes can take a list as first argument to further simplify the code. – celtschk Feb 11 '12 at 10:16
  • 1
    I just noticed that you should be able to easily get around this by loading the module inside a block like this: Block[{Locked=ReadProtected},Get["yourpackage`"]]. – celtschk Feb 14 '12 at 18:19
  • 7
    Not anymore in Version 9, since now, finally, Locked is Locked ... – Rolf Mertig Dec 30 '12 at 16:47
  • @RolfMertig how did you come across that? Useful info! – Yves Klett Dec 30 '12 at 16:59
  • @Yves Klett That was one of the first things I checked when I started with V9 (beta). That Locked was not Locked until then was first brought to my attention some years ago by a fellow Mathematica freak. – Rolf Mertig Dec 30 '12 at 17:02
  • @YvesKlett Probably it is now possible to write pretty safe Mathematica code. I might write a small package to do so. – Rolf Mertig Dec 30 '12 at 17:02
  • @RolfMertig by all means! Guten Rutsch! – Yves Klett Dec 30 '12 at 17:06
  • 1
    @RolfMertig - Did you ever get to doing this? Any additional thoughts? – Jagra Apr 25 '14 at 12:34
  • @Jagra No, I just don't know how safe Encode really is ... – Rolf Mertig Apr 26 '14 at 18:27