[REBOL] Re: Rebol Product Suggestion.
From: joel:neely:fedex at: 24-Jun-2001 3:16
Gabriele Santilli wrote:
> JN> Unless RT adds a primitive that's the equivalent of
>
> JN> do decrypt somestring
> JN> somestring: ""
>
Let me detail this to
do-crypt: make native! [voodoo-stuff] [
hidden-buffer: decrypt voodoo-stuff
block-buffer: load hidden-buffer
clear hidden-buffer
do block-buffer
clear block-buffer
]
(terrible hypothetical REBOL style, just to make the point).
> Yes, but then again with proper reverse engeneering one could
> get to the source anyway. A "lossy" conversion, instead,
> guarantees that noone can get to the original source in any
> way.
>
Assuming that there's no such thing as perfectly secure
encryption, there's always *some* way to crack something. As
you pointed out earlier, compiled binaries can be analyzed and
disassembled. However, few people have sufficient time, money,
tools, skills, patience, and motivation (i.e., "cost" factors)
to reverse engineer a reasonably-sized binare.
IMHO the game is about simply raising the costs high enough that
most people won't bother. That's why I suggest the "do-crypt"
option. If the decrypted source only exists in a buffer long
enough for REBOL to load it to an internal data structure,
which only exists long enough to be DOne, and all of the above
is done within a native that can't be examined with SOURCE,
then the distributed source code is much more secure than if
the decryption were done by the user and/or left in a user-
accessible place in memory.
Of course, the attacker could still hook up a logic analyzer,
use an ICE debugger, or run a Pentium emulator on his friendly
neighborhood Beowulf, etc., but those options all raise the
costs beyond most users' means.
You're absolutely right that "shrouding" the code (in the sense
we were discussing and I illustrated) would further raise the
costs if combined with do-crypt.
> what about:
>
> propercase: func [s]
> [head lowercase next uppercase/part copy s 1]
>
Nice! (But you didn't show how that change would affect the
shrouded copy! ;-)
> JN> result: copy nextsep: ""
>
> BTW, in these cases I usually write:
>
> result: clear ""
> ; ...
> copy result
>
> because that will probably require less memory allocations.
> After calling the function a couple times, indeed, the result
> buffer will automatically end up being as large as needed and
> no more memory allocations and copying will be needed in
> future calls, except for the explicit final copy. (Well, I
> couldn't resist giving my $0.02. :)
>
That's an interesting approach; let me think out loud...
result: copy ""
;...
result
... copies a trivial string initially, then reallocates and
copies (some number of times/quantities) as the result grows
during each function invocation.
result: clear ""
;...
copy result
... on repeated use: clears and copies a string with allocation
equal to the longest result produced in any use.
I can think of all sorts of interesting benchmarks for the
behavior of CLEAR, COPY, and APPEND (the hidden allocations)
but the surface-level trade-off would seem to be a variation
on the classical time-for-space. If an abnormally large result
occurred early in a long-running process, then option two would
keep that amount of memory tied up and subsequently unused
forever (i.e., until REBOL quits).
That being the case, does
result: make string! some-normally-large-enough-size
;...
result
sound like a middle-ground compromise to you?
> JN> - Replace simple constants/expressions with more obscure
> JN> expressions
>
> Mainly for strings, so that they are not easyly readable by
> the "intruder".
>
Depending on the application, one may be as likely to want to
hide some "magic numbers" as well. The technique works for
both. Didn't you notice that I used
index? head lOOO1
as a shrouded way to get a 1? ;-)
> JN> yet know how to program the required knowledge. I'll be
> JN> fascinated to see any progress you might make! Good
> luck!
>
> I'll need luck, I know! :-) But I think it can be done to some
> extent...
>
Agreed. I had been thinking about the "full blown" problem
of taking an arbitrary REBOL source file and trying to shroud
it. Unfortunately, the task of figuring out which words were
my words versus system words (versus somebody-else's words?)
began to look quite hairy given the possibility of DO and BIND
appearing in the code.
One of the cleverest shrouding tricks I've seen used "key
words" randomly as replacements for local variables, etc.
The analog in REBOL would be to turn something like
ply: func [
{create a string from series and separator arguments}
ser [series!] {series of values to be collected}
sep [string! char!] {value to go between elements}
/local
result {accumulator for string}
nextsep {what precedes next item?}
][
result: copy nextsep: ""
foreach item ser [
repend result [nextsep item]
nextsep: sep
]
result
]
into
ply: func [print [series!] = [string! char!] /local
probe word? ] [ probe: copy word?: "" foreach to
print [ repend probe [ word? to ] word?: = ] probe ]
which actually works... ;-)
Highly effective shrouding IMHO, but requires even more
semantic knowledge of REBOL to pull it off.
-jn-
------------------------------------------------------------
Programming languages: compact, powerful, simple ...
Pick any two!
joel'dot'neely'at'fedex'dot'com