7
$\begingroup$

I have written a Mathematica package on game theory (containing functions that tests whether a game is perfect recall, finds optimal strategies for a player in a game, etc.) and would like people to be able to use it (execute its functions). However, I don't want people to be able to analyze how the algorithms work. Is there a way (does Mathematica have the feature or have someone made a program) to obfuscate Mathematica functions so that a function is translated to another function that works exactly the same in terms of input-output but is completely unreadable? I don't need to have the obfuscated function be translatable back to the original function (using a secret keyword, as in encryption-decryption scheme), because I have the original function saved privately anyway.

As a comparison, Maple 2018 has this (new) feature: https://www.maplesoft.com/products/maple/new_features/Maple2018/EncryptedProcedures.aspx

$\endgroup$
  • 2
    $\begingroup$ I think you need Encode? $\endgroup$ – xzczd Jun 27 '18 at 17:19
  • 2
    $\begingroup$ Take a look at this tutorial: wolfram.com/broadcast/video.php?c=89&v=596&p=1 $\endgroup$ – TreFox Jun 27 '18 at 17:20
  • 2
    $\begingroup$ It isn't obvious how to do this, aside from creating a deployed CDF like in the video linked above. You could make a WL package, written to an MX file so the source isn't readable. You can set your functions to have the ReadProtected attribute, but there isn't a way to hide the DownValues from users. $\endgroup$ – Jason B. Jun 27 '18 at 17:27
  • 1
    $\begingroup$ @JasonB. actually if you also supply Locked along with ReadProtected no definitions can be read. $\endgroup$ – b3m2a1 Jun 27 '18 at 19:02
12
$\begingroup$

This is what a combination of Locked, Encode, and ReadProtected do for you. As xczd notes in the comments, Encode makes the source code unreadable to humans. You can also supply an encoding key, as I do here.

Then if you set both Locked and ReadProtected you won't be able to inspect the DownValues (or any *Values) of your symbol. Here's an example that allows you to make a cache where the cache keys and values can't be read:

SetAttributes[Caches`$myCache, {ReadProtected, Locked}]
Caches`$myCache["user"] = "password";
Caches`$myCache // DownValues

General::readp: Symbol Caches`$myCache is read-protected.

$Failed

Caches`$myCache["user"]

"password"

Note that Locked is a heavy attribute, though. I can no-longer change any of the Attributes of this function, nor can I remove it.

Caches`$myCache // Remove

Remove::rmlck: Symbol Caches`$myCache is Locked and cannot be removed.

One other subtle thing worth noting is that ReadProtected alone is not enough:

SetAttributes[Caches`$myCache2, {ReadProtected}]
Caches`$myCache2["user"] = "password";
Caches`$myCache2 // DownValues

{HoldPattern[Caches`$myCache2["user"]] :> "password"}
$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.