This is a start that could be turned into a style and a package, and improved, etc.
First, some function to encrypt a string with a key. I'm not good at this, I only knew how to do it with Encode
encode[expr_, password_String] :=
With[{fnameSource = FileNameJoin[{$TemporaryDirectory, "encrSource"}],
fnameDest = FileNameJoin[{$TemporaryDirectory, "encrDest"}]},
Block[{buff},
Put[Unevaluated[buff = expr], fnameSource];
Encode[fnameSource, fnameDest, password];
With[{res = StringJoin@Import[fnameDest, {"Binary", "Character8"}]},
Scan[DeleteFile, {fnameSource, fnameDest}];
res
]
]]
To decode
decode[expr_String, password_String] :=
With[{fname = FileNameJoin[{$TemporaryDirectory, "decr"}]},
Export[fname, Characters@expr, {"Binary", "Character8"}];
Block[{buff},
Quiet@Check[Get[fname, password], buff = $Failed];
With[{res = buff},
DeleteFile@fname;
res]
]]
The idea is simple: to provide a button in a CellFrameLabel
, that encrypts or decrypts the cell's content
Let's overload our previous functions, letting them take a cell object
encode[co_CellObject] :=
With[{pass = InputString["Please, enter the password"]},
CurrentValue[co, {TaggingRules, "encoded"}] = True;
NotebookWrite[co,
Replace[NotebookRead[co],
Cell[data_, opts___] :>
Cell[BoxData@
ToBoxes@Interpretation["Hidden cell",
Evaluate@encode[data, pass]], opts]]];
SelectionMove[EvaluationNotebook[], After, Cell];
]
decode[co_CellObject] :=
With[{pass = InputString["Please, enter the password"]},
With[{newCell = Replace[
NotebookRead[co],
Cell[BoxData[int_], opts___] :>
Cell[decode[ToExpression@int, pass], opts]]},
(CurrentValue[co, {TaggingRules, "encoded"}] = False;
NotebookWrite[co, newCell];
SelectionMove[EvaluationNotebook[], After, Cell]) /;
MatchQ[newCell, Cell[Except[$Failed], ___]]]
]
decode::fail = "Failed to decode cell";
decode[_CellObject] := (Message[decode::fail]; $Failed /; False)
These are the options an "encryptable cell" should have. Just a tagging rule with the state (encrypted or not encrypted), and the cell frame label specifications.
opts = Sequence[
CellFrameLabels -> {{None, None}, {None, ToBoxes@Dynamic[
CurrentValue[{TaggingRules, "encoded"}] /. {
False :> {"Encode", encode},
True :> {"Decode", decode}} /. {butName_, fun_} :>
Button[butName,
fun[SelectionMove[EvaluationNotebook[], All,
EvaluationCell]; First@SelectedCells[]],
Method -> "Queued"]]}},
TaggingRules -> {"encoded" -> False}];
So, for example, try
CellPrint@ExpressionCell[28 f[9], "Output", opts]
or
CellPrint@TextCell["The answer is 8", "Text", opts]
You can put this into a stylesheet, and the functions into a package.