RubyEncoder allows to protect Ruby and Ruby on Rails files by compiling and encrypting them. The encoded scripts are then run by RubyEncoder's loader. RubyEncoder is developed by Inovica Ltd, which also created a smiliar tool for PHP: SourceGuardian.
RubyEncoder can also be used to only partly protect a project, allowing plaintext Ruby and configuration files; or to limit an application to a certain host or only for a limited time period to create a trial version (more scenarios can be found in the RubyEncoder FAQ section).
InfoQ talked to Alexander Belonosov RubyEncoder's lead developer to learn more about the technical side of the project.
InfoQ: How does the encoding and the loading/running work?
The Ruby source code is compiled into an intermediate internal format which is followed by encryption. The original source code does not exist in protected scripts once they are encoded. RubyEncoder Loader needs to be installed to run protected scripts. The loader is a Ruby extension which decodes the protected script and runs it. Protected scripts are platform independent which is very important and you may use protected scripts on any supported platforms. Loaders differ for OS and platforms. We support the following platforms for running RubyEncoder protected scripts - OSX, Linux, FreeBSD and we are just started Solaris x86 support. We have plans to add support for Windows and other UNIX in the nearest future.
InfoQ: The source is translated to an intermediate format. Do you have your own interpreter that runs it or do you restore the original Ruby source code?
The original Ruby source code is never restored. We use internal intermediate format. [..] It is internal, binary, executable and never decodes back to original source code.
InfoQ: If you have your own interpreter, how does this interact with metaprogramming and other dynamic behavior of Ruby? Or are there no restrictions whatsoever?
Currently the loader passes the internal representation of the code back to Ruby for execution. This lets us to keep maximum compatibility and a dynamic nature of the Ruby code. But we also keep looking on other methods and possibly will change or implement a new schema in next versions of our product. Anyway using of RubyEncoder protected products will be transparent to end-users and Ruby developers will get an updated and more effective encoder.
InfoQ: With the ParseTree gem, one can access the parse tree of a class or method. Is this affected by RubyEncoder?
ParseTree is a great extension for investigating internals of Ruby, code optimisation etc. If you mean if we restrict to use ParseTree then the answer is no. But what is important to understand when you use tools like ParseTree is what you need to extract from Ruby internals and how to find it. I think it is also important to think of what is a reason for it, how much time will it take and what will be a final result :-)
InfoQ: Do you have plans to support other Ruby implementations, for example JRuby? Would it be possible to port the loader to Java to run JRuby code?
Currently we support only standard Ruby. JRuby is great project and it is growing. Although it has a bit different market.
InfoQ: Using JRuby and compiled Ruby sources, would ByteCode obfuscation lead to the same protection that RubyEncoder provides?
Using JRuby and compiled Ruby sources may produce a very good level of protection. But it is oriented for a Java environment. Our aim is to protect native Ruby and Ruby-on-Rails project initially and we may decide to look at enhancing or expanding the product later.
InfoQ: In what language is RubyEncoder written? Using Ruby and then self-encoded?
No, I have nothing bad to say about Ruby meta programming :-) But RubyEncoder and the loaders are written in C.
RubyEncoder is a commercial product, there's also a 30 days trial version available.
Have you ever used such a code protection tool? What were your experiences with it?
Community comments
Easily circumvented
by Michael Guterl,
Is this a good idea?
by Joshua Partogi,
Re: Is this a good idea?
by Francois Ward,
Re: Is this a good idea?
by Charles Nutter,
Re: Is this a good idea?
by Oyku Gencay,
Easily circumvented
by Michael Guterl,
Your message is awaiting moderation. Thank you for participating in the discussion.
As Dmitry Severin points out on the ruby-talk mailing list this is easily circumvented...
blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby...
Is this a good idea?
by Joshua Partogi,
Your message is awaiting moderation. Thank you for participating in the discussion.
If you want to protect your ruby code, why not run under JRuby on production and compile it to Java bytecode instead?
Re: Is this a good idea?
by Francois Ward,
Your message is awaiting moderation. Thank you for participating in the discussion.
Because java bytecode isn't even THAT hard to -read-, nevermind decompile. Same deal in .NET. If you want people to take more than 15 minutes to go through it, you'll need to obfuscate it too.
Re: Is this a good idea?
by Charles Nutter,
Your message is awaiting moderation. Thank you for participating in the discussion.
Francois: Being able to read the bytecode is a long way from being able to convert it back into Ruby code. Some of the bytecode generated by JRuby can be converted into Java code, but there's no decompiler to bring it all the way back to Ruby. Making anything out of the decompiled Java code is nearly impossible, since it's essentially all calls to JRuby internal APIs. Compiling under JRuby provides at least as good obfuscation, and it has the added benefit of running faster than other Ruby implementations. And it's free.
Re: Is this a good idea?
by Oyku Gencay,
Your message is awaiting moderation. Thank you for participating in the discussion.
The tune of the idea of compiling ruby to JVM bytecode sonds nice. But try this with a fullblown rails app. I could not find any resource on this. As soon as you "compile" with JRuby you're out of the rubyland. None of the mainstream deployment methods took this into consideration. Even the Warbler has an compile_ruby = true option which basically does not work