Given that your customers have a Mathematica license, is there a way to sell executable code to them without giving away your proprietary source code too?
Rolf [Hi Rolf! How are things going?] is almost correct about Encode.
Encode has the ability to encrypt the encoded file with a key which would then be required to read in the file using Get. Encode also can take an option that restricts it to only be allowed to be read on a specific machine with a specified value of $MachineID. Note that if one does encrypt (or restrict or both) the Encoded file in this way, one still needs to make use of Protected and Locked to thwart (at least to some degree) the ability of the user to reverse engineer the internal code.
Probably Encode and tricks as David outlined are enough for the normal client.
However, the more fundamental problem is that Encode
does not encrypt. So by definition it is not safe (see e.g. : here).
The only really safe way (if you protect your webserver from behing hacked into),
is to use good old webMathematica, since the Wolfram Language source code only resides on the server,
just the input and output is transferred from and to the user.
If you do not mind that your code is in the cloud (i.e., always readable by some
system administrator at Amazon or Wolfram at least), the Wolfram Programming Cloud might also be a possibility,
once it is out of Beta, of course.
It is subtle and requires a number of steps, some of which might conflict with the functionality of the code itself. If you are talking about a Package then some of the steps that you can take to make it difficult for a user to read and reverse-engineer the code is to:
(a) Set the Protected attribute for all functions and parameters except those that need, for functionality reasons, to remain Unprotected
(b) Set the Locked attribute for all functions and parameters except those that need, for functionality reasons, to remain not Locked. Make sure all functions and parameters in the Private sub-context of the package have the Locked attribute.
--- Note that one cannot use the SetOptions function on a function that has a Locked attribute: it will have no effect and will generate an error.
--- Any parameters or functions that are ever reset inside of the package must not be Locked. So any such functions or parameters will be reverse engineerable by the user
--- Also note that a package with Locked parameters cannot be reloaded with Get
(c) Finally you must Encode the package .m file to a file of the same name so that its ASCII representation is not human decipherable.
Adding password protection is an additional layer of complexity. I have a way to do it, but it's not foolproof (and hence something I keep confidential.) But it involves deleting the full set of functions and parameters in the package's context if the user does not provide the correct password. This has to be checked and carried out before setting any of the above Locked and Protected attributes.