Skip to content

cc Ajaxmin Obfuscator #380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: cc
Choose a base branch
from
Open

cc Ajaxmin Obfuscator #380

wants to merge 3 commits into from

Conversation

lduchosal
Copy link

Dear Nikhil,

I've added an AjaxMin obfuscation engine to ScriptSharp.
It uses metadata (symbols) gathered during ScriptSharp compilation to create AjaxMin rename/norename file.

Obfuscation process has 3 modes: None, X, Full defined in the .csproj (see ScriptSharpWeb.targets)
X : will prefix obfuscated names with a X. It greatly helps debugging JavaScript while validating obfuscation.
Full : will make your JavaScript human unreadable.

You can prevent obfuscation on class/properties/methods with the ScriptImport and ScriptAlias attributes. This is helpful if you use Enum names in your code and don’t want them to be renamed in obfuscated JavaScript.

Changes to ScriptSharp generator are insignificant. I hope this pull request will make its way into the main repository.

Regards

lduchosal added 3 commits April 26, 2013 17:36
Modified ss.Bind to ease AjaxMin obfuscation
Removed KeepDuplicates from WebTarget because of UnexpectedAttribute Error
@nikhilk
Copy link
Owner

nikhilk commented Jun 13, 2013

Its generally better to discuss such large changes before an actual pull request. Lots of questions come to mind. Some important ones that are independent of actual code:

  • What is the goal of the obfuscation that is not achieved by the minimization (which is already done using AjaxMin)?
  • Why is the obfuscation part of deployment? Minimization is part of the build process... and assuming obfuscation adds specific value above and beyond minimization, it is better modeled as a minimization mode rather than a completely separate concept.
  • ScriptImport/ScriptAlias have existing semantics. We'd want to introduce something like PreserveName. Or maybe even leverage ScriptName since that already plays into naming. Enums with ScriptConstants(UseName = true) shouldn't be minimized to begin with (i.e. without requiring additional attributes).
  • I am not sure why the generator should change - minimization is completely done as an after step, and so should obfuscation. The only thing that sounds like should be generated to feed into this after-step is the rename/norename file.
  • Additionally, what is the purpose of the symbol file. It seems a symbol file is generated which then is used to generate the rename file. We should just generate what is needed without generating more intermediate files.

@lduchosal
Copy link
Author

Dear Nikhil,

Thanks for your time and thanks for providing us with ScriptSharp.

  • Minimization is not obfuscation. Todays AjaxMin minification is "Removing spaces and new lines". This is easily reversible. AjaxMin does un-minimify javascript code given the proper switches. On the other hand, obfuscation is a lossy process and cannot be reverted without greatest efforts. The resulting obfuscated code is not readable neither understandable by human anymore.
  • We need to gather as much informations as we can about each and every compiled project to make it deep and strong obfuscation. Otherwise, we end up obfuscating only private and internal members, leaving public ones clear, readable and understandable. So the later the obfuscation happens the wider, deeper and stronger it is.
    Yet, I have code for "live obfuscation", to obfuscate js file with randomly generated renames maps on a per request basis. I would gladly contribute it, but that require server side components that ScriptSharp isn't burdened with.
  • I do agree that we could create new attributes to fine tune obfuscation. However, I wanted the footprint on scriptsharp to be as small as possible. You'll see that no line in the script generation has been added, neither the way ScriptSharp works. (ImportMetadata(), BuildCodeModel() BuildMetadata(), BuildImplementation(), GenerateScript() are left untouched).
    The main part of the work was to create the symbol files to gather as much informations on the build process for the obfuscation to be really effective.
  • Obfuscation can happen only after everything has been built, when we have all the symbols of all projects at our disposal. That's the reasons the obfuscation is made later on at the deployment step.
    [IMHO] ScriptSharp does convert c# to JavaScript and does it well. AjaxMin does good job at removing spaces, but I'd leave it outside ScriptSharp core. That would be "separation of concern". [/IMHO]
  • Symbol file is a dump of the SymbolSet that is used to generate rename/norename file.
    Symbol file need to exists until every project has been compiled to javascript. It will then be transformed and the end of the process.
    Symbol file reflects the inner objects of ScriptSharp and might be used for other purposes (debugging).
    Symbol file is big, I was afraid of having it around in memory for too long.
    I do agree though, that Symbol file has to be removed once rename/norename files have been generated.

Best regards

@nikhilk
Copy link
Owner

nikhilk commented Jun 16, 2013

Yes, I do get the distinction between minimization and actual obfuscation, and this would certainly help those who need to obfuscate in addition.

It sounds like to be effective, you want to obfuscate a set of libraries at a time, rather than minimization which works at the level of a single file. That is fine. However, that suggests obfuscation is a separate tool, and doesn't need to be in the core script# pipeline, because the script# compiler works at the level of a single assembly/script. What we should do is produce the symbol file from the script#, but make it json rather than xml (.jsi? - .js info). XML just seems antiquated. The symbol file contains literally whatever symbol info we got from c#. It doesn't contain any renaming done for obfuscation... as that is the job of the obfuscator.

The deployment msbuild task isn't necessarily the right place to do obfuscation either, since a web app may or may not have all scripts deployed via that mechanism. So again, obfuscation would be a separate tool.

This separate obfuscator tool works against the produced .js and .jsi files to do whatever it needs. Any options etc. for obfuscation do not need to affect the script# compiler.

What we should do in script# is go ahead and define explicit semantics for preserving name - we should update the existing ScriptName attribute to add those new capabilities. For example, specifying an explicit script name both supplies generated name as well as suppresses obfuscation... what we need to add is ability to suppress obfuscation without specifying an explicit name.

Makes sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants