Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Rebol Product Suggestion.

 [1/11] from: ptretter:charter at: 22-Jun-2001 14:42


Heres an idea - just make two scripts - one of the scripts converts a script file into some binary system that you define and then another that you create interprets the binary script you dumped. That way you can distribute the interpreter and script processor along with your encyrpted/binary script. Paul Tretter

 [2/11] from: depotcity::telus::net at: 22-Jun-2001 13:24


But then the user could use the interpreter to read the script. However, I think your on the right track. You could have an encrypted script that was decrypted by reading a decryption string from a server.. but that is slow, requires network access etc. There must be a more effective method??? Terry

 [3/11] from: depotcity:telus at: 22-Jun-2001 10:40


Hi. Here's a Rebol product that I would buy. An script encapsulator that simply converts a script to binary form, but unlike the runtime, without the core/command engine attached. Just something to prevent short scripts from being read. With the runtime, if you encapsulate a 1kb script, you end up with a 254kb monster! Terry Brownell

 [4/11] from: holger:rebol at: 22-Jun-2001 10:50


On Fri, Jun 22, 2001 at 10:40:16AM -0700, Terry Brownell wrote:
> Hi. > > Here's a Rebol product that I would buy. > > An script encapsulator that simply converts a script to binary form, but unlike the runtime, without the core/command engine attached. > > Just something to prevent short scripts from being read.
REBOL would have to convert it back to text form in order to interpret it, and at that time users would still see the script. -- Holger Kruse [holger--rebol--com]

 [5/11] from: dness:home at: 22-Jun-2001 13:54


Terry Brownell wrote:
> Hi. > > Here's a Rebol product that I would buy. > > An script encapsulator that simply converts a script to binary form, but unlike the runtime, without the core/command engine attached. > > Just something to prevent short scripts from being read. > > With the runtime, if you encapsulate a 1kb script, you end up with a 254kb monster! > > Terry Brownell >
I'm not sure I'd use `monster' to describe a 254kb file. Cluster size on my most recent large disk is 256kb. anyway, so such things don't really cost me all that much. I wonder if things like this will worry us for long?

 [6/11] from: g:santilli:tiscalinet:it at: 23-Jun-2001 15:00


Hello Terry! On 22-Giu-01, you wrote: TB> But then the user could use the interpreter to read the TB> script. However, I think your on the right track. You could TB> have an encrypted script that was decrypted by reading a TB> decryption string from a server.. but that is slow, requires TB> network access etc. There must be a more effective method??? Encryption never gives you security over source code. To execute you have to decrypt, so any user has to be able to decrypt. This means that encryption is just a waste of time in this case --- why not just use compression instead? Please consider that even .exe binary files are "readable", in the sense that you can disassemble the machine language etc. Of course, very few people wants to disasseble and reverse engeneer a big and complex program, and this is what makes people happy about distributing binary only programs. In the case of REBOL, noone stops you from creating a very unreadable script that cannot be (easyly) understood or modified by a human but that can be evaluated by the REBOL interpreter. The alien language script from the library is an example, and you can get even more trickier if you want (e.g. hiding checksums around so that modifing is intercepted by the program). What I'd do is creating a script that takes a normal (commented, readable etc.) REBOL script and writes out another script that does exactly the same thing as the first but is not readable by humans. (I'm likely to write something like this sooner or later as I might need it.) Regards, Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/

 [7/11] from: joel:neely:fedex at: 23-Jun-2001 4:18


Hi, Gabriele, Your remarks are inspiring, as usual! (Of course there's a fine line between inspiration and madness. ;-) Gabriele Santilli wrote:
> Encryption never gives you security over source code. To > execute you have to decrypt, so any user has to be able to > decrypt. >
Unless RT adds a primitive that's the equivalent of do decrypt somestring somestring: "" (per a discussion at least a year ago on this list).
> In the case of REBOL, noone stops you from creating a very > unreadable script that cannot be (easyly) understood or
<<quoted lines omitted: 4>>
> another script that does exactly the same thing as the > first but is not readable by humans.
I played with this idea a while back. We could begin with 8<-------------------------------------------------------- propercase: func [ {capitalize first letter only of a string} s [string!] {original string - unchanged} ][ head change lowercase copy s uppercase copy/part s 1 ] 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 ] map: func [ {return mapped-function results for all ser items} [catch] ser [block! hash! string!] {inputs} mapped-function [any-function!] /all {return none? values?} /local res {result block} val {single-item result value} ][ res: make type? ser length? ser throw-on-error [ foreach item ser [ if any [ found? val: mapped-function item all ][ append/only res val ] ] ] res ] capitalize: func [ {return string with uppercased first letters} s [string!] {unmodified input} ][ ply map parse s none :propercase " " ] 8<-------------------------------------------------------- And apply rules such as: - Remove comments. - Never allow meaningful names - Use names hard to distinguish - Replace simple constants/expressions with more obscure expressions - Never allow whitespace to reveal structure and arrive at 8<-------------------------------------------------------- capitalize: func [ I1l1I [string!] /local O0Ol0 IIOOO ] [ O0Ol0: func [ OO01O [series!] O00I0 [string! char!] /local OOOIO O0010 ] [ OOOIO: copy O0010: copy tail mold 17 foreach O0OIO OO01O [ repend OOOIO [O0010 O0OIO] O0010: O00I0 ] OOOIO ] IIOOO: func [ IIOOI [block! hash! string!] IIOO1 [any-function!] /IIO0I /local II000 III0l ] [ II000: make type? IIOOI length? IIOOI foreach II1Ol IIOOI [ if any [ found? III0l: IIOO1 II1Ol IIO0I ] [ append/only II000 III0l ] ] II000 ] O0Ol0 IIOOO parse I1l1I none func [ lOOO1 [string!] ] [ head change lowercase copy lOOO1 uppercase copy/part lOOO1 index? head lOOO1 ] to-string to-char 32 ] 8<--------------------------------------------------------
> (I'm likely to write something like this sooner or later > as I might need it.) >
However, I found that some of those rules were VERY hard to describe in purely syntactic terms, actually requiring an ability to read and understand REBOL. Since I'm still working on creating a model that *I* can understand, I don't yet know how to program the required knowledge. I'll be fascinated to see any progress you might make! Good luck! -jn- ------------------------------------------------------------ Programming languages: compact, powerful, simple ... Pick any two! joel'dot'neely'at'fedex'dot'com

 [8/11] from: g:santilli:tiscalinet:it at: 24-Jun-2001 12:09


Hello Joel! On 23-Giu-01, you wrote: JN> Your remarks are inspiring, as usual! (Of course there's JN> a fine line between inspiration and madness. ;-) ;-) JN> Unless RT adds a primitive that's the equivalent of JN> do decrypt somestring JN> somestring: "" JN> (per a discussion at least a year ago on this list). 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. JN> propercase: func [ JN> {capitalize first letter only of a string} JN> s [string!] {original string - unchanged} JN> ][ JN> head change lowercase copy s uppercase copy/part s 1 JN> ] what about: propercase: func [s] [head lowercase next uppercase/part copy s 1] 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. :) JN> And apply rules such as: JN> - Remove comments. ;-comments will be removed by load. String comments could be removed automatically in places such as function definitions etc., but maybe it would be better if is the programmer to manually remove them. JN> - Never allow meaningful names This can be done by changing non-system words and by aliasing system words. Human intervention may be necessary in some cases. JN> - Use names hard to distinguish I'd say completely random. :) JN> - Replace simple constants/expressions with more obscure JN> expressions Mainly for strings, so that they are not easyly readable by the intruder . JN> 8<-------------------------------------------------------- JN> capitalize: func [ I1l1I [string!] /local O0Ol0 IIOOO ] [ JN> O0Ol0: func [ OO01O [series!] O00I0 [string! char!] /local JN> OOOIO O0010 ] [ OOOIO: copy O0010: copy tail mold 17 foreach JN> O0OIO OO01O [ repend OOOIO [O0010 O0OIO] O0010: O00I0 ] JN> OOOIO ] IIOOO: func [ IIOOI [block! hash! string!] IIOO1 JN> [any-function!] /IIO0I /local II000 III0l ] [ II000: make JN> type? IIOOI length? IIOOI foreach II1Ol IIOOI [ if any [ JN> found? III0l: IIOO1 II1Ol IIO0I ] [ append/only II000 III0l JN> ] ] II000 ] O0Ol0 IIOOO parse I1l1I none func [ lOOO1 JN> [string!] ] [ head change lowercase copy lOOO1 uppercase JN> copy/part lOOO1 index? head lOOO1 ] to-string to-char 32 ] JN> 8<-------------------------------------------------------- This is a very good example of what I intended. Thanks Joel! 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, as long as either the programmer helps the tool doing the conversion or (s)he writes the source code in a format that can be easyly automatically processed (giving hints to the processor, that is). Regards, Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/

 [9/11] 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:
<<quoted lines omitted: 7>>
> 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

 [10/11] from: g:santilli:tiscalinet:it at: 24-Jun-2001 23:12


Hello Joel! On 24-Giu-01, you wrote: JN> IMHO the game is about simply raising the costs high enough JN> that most people won't bother. That's why I suggest the Absolutely. JN> Nice! (But you didn't show how that change would affect the JN> shrouded copy! ;-) Left as an exercise to the reader . ;-) JN> I can think of all sorts of interesting benchmarks for the JN> behavior of CLEAR, COPY, and APPEND (the hidden allocations) JN> but the surface-level trade-off would seem to be a variation JN> on the classical time-for-space. If an abnormally large JN> result occurred early in a long-running process, then option JN> two would keep that amount of memory tied up and subsequently JN> unused forever (i.e., until REBOL quits). I think so... JN> That being the case, does JN> result: make string! some-normally-large-enough-size JN> ;... JN> result JN> sound like a middle-ground compromise to you? Yep. But it's not always that easy to choose some-normally-large-enough-size in a way that makes everyone happy. (Of course. :) Anyway, I just thought that it would have been useful to point out that there are many possibilities to choose from, and your analisys will surely help choosing! JN> Agreed. I had been thinking about the "full blown" problem of JN> taking an arbitrary REBOL source file and trying to shroud JN> it. Unfortunately, the task of figuring out which words were JN> my words versus system words (versus somebody-else's words?) JN> began to look quite hairy given the possibility of DO and JN> BIND appearing in the code. I think an acceptable solution could be the following: * the programmer puts all the code together in a huge script. * the tool loads the script and checks words versus what is in system/words; if a word is in system/words, it is put in the list of words to be aliased. * the tool spits out some unreadable and tricky code to alias the words in the list. * all the other words are simply substituted. What is more difficult is to find a way to automatically substitute simple expressions or literal values with trickier ones. I think this will need at least some human assistance. Any idea? JN> ply: func [print [series!] = [string! char!] /local JN> probe word? ] [ probe: copy word?: "" foreach to JN> print [ repend probe [ word? to ] word?: = ] probe ] This is nice, too. But I'm afraid it would be almost impossible to do automatically... (as you point out, too) Regards, Gabriele. -- Gabriele Santilli <[giesse--writeme--com]> - Amigan - REBOL programmer Amiga Group Italia sez. L'Aquila -- http://www.amyresource.it/AGI/

 [11/11] from: agem:crosswinds at: 25-Jun-2001 2:01


RE: [REBOL] Re: Rebol Product Suggestion. [g--santilli--tiscalinet--it] wrote:
> Hello Joel! > > On 24-Giu-01, you wrote: >
--snip--
> JN> ply: func [print [series!] = [string! char!] /local > JN> probe word? ] [ probe: copy word?: "" foreach to > JN> print [ repend probe [ word? to ] word?: = ] probe ] > > This is nice, too. But I'm afraid it would be almost impossible to > do automatically... (as you point out, too) >
[REBOL [ title: "translate rebol-scripts to another language" content: true file: %trans3.r comment: { had a quick look on hd, not sure what this is ;-) feature: translates words in pathes too, so this/that would go dies/das . based on Carls %clean-script.r PROTOTYP, own risks and that! ;-) } ] script-cleaner: make object! [ a: none to-type: func [t w] [ do load mold compose/deep [to (type? :t) first [(:w)]] ] any-path?: func [s] [ any [path? :s set-path? :s lit-path? :s] ] deutsch: make hash! [ ;rebol = any-word? ein-wort? any manche append ha&ng-an change a&ndere clear sa&ubere compose stelle-zusammen copy kopiere deep tief difference unterschied do tue does tut either entscheide emit gib-aus end text-ende first erstes forall *jeder forskip *gruppiert found? gefunden? func rezept hash schnellfinder head anfang if wenn last letztes load lade mold rebol-text newline neue-zeile next danach parse analysiere pick nimm-nr remove entferne-an set setze select wa&hle-aus skip u&berspringe some einige sort sortiere tail ende thru durch to zu true richtig unique ohne-doppelte ;meins a a new neu value wert ] forskip deutsch 2 [change deutsch to string! first deutsch] deutsch: head deutsch words: copy [] w: func [w /local e o] [ append words to word! :w e: select deutsch to string! to word! :w either e [to-type :w :e] [:w] ] out: none ; output text spaced: off ; add extra bracket spacing indent: "" ; holds indentation tabs emit-line: func [] [append out newline] emit-space: func [pos] [ append out either newline = last out [indent] [ pick [#" " ""] found? any [ spaced not any [find "[(" last out find ")]" first pos] ] ] ] emit: func [from to] [emit-space from append out copy/part from to] set 'clean-script func [ "Returns new script text with standard spacing." script "Original Script text" /spacey "Optional spaces near brackets and parens" /local str new ] [ spaced: found? spacey out: append clear copy script newline parse script blk-rule: [ some [ str: newline (emit-line) | #";" [thru newline | to end] new: (emit str new) | [#"[" | #"("] (emit str 1 append indent tab) blk-rule | [#"]" | #")"] (remove indent emit str 1) | skip (set [value new] load/next str any [ if any-word? :value [emit a: mold w :value tail a true] if any-path? :value [ forall value [if any-word? value/1 [value/1: w value/1]] value: head :value emit a: mold :value tail a true ] do [emit str new] ] ) :new ] ] remove out ; remove first char ] dump: does [ probe sort unique script-cleaner/words a: copy [] forskip deutsch 2 [append a to word! deutsch/1] deutsch: head deutsch probe sort exclude words a ] ] ? 123 save f: system/script/header/file load/header system/script/header/content print example: clean-script read f ;script-cleaner/dump ]
> Regards, > Gabriele.
;-) Volker

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted