npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

gnirts

v1.1.8

Published

Obfuscate string literals in JavaScript code.

Downloads

1,158

Readme

gnirts

npm GitHub issues dependencies license

Obfuscate string literals in JavaScript code.

Online Demonstration https://anseki.github.io/gnirts/

gnirts mangles string literals more than hexadecimal escape like "\x66\x6f\x6f".
String literals that were escaped by the hexadecimal escape can be found out too easily, and those can be decoded too easily. Those stand out in the code. Stealers can get secret text (e.g. password) easily by pasting that on a console (e.g. Developer Tools of web browser).

gnirts mangles string literals by using some codes instead of hexadecimal escape. gnirts might not be able to protect the string from stealers perfectly, but it forces a troublesome work upon them. (See Note.)

For example, a string that should be hidden is here:

var password = 'open sesame';

Add the directives:

var password = /* @mangle */ 'open sesame' /* @/mangle */;

And then, pass this code to gnirts. The string literal between /* @mangle */ and /* @/mangle */ is obfuscated:

var password = (function(){var v=Array.prototype.slice.call(arguments),V=v.
shift();return v.reverse().map(function(U,o){return String.fromCharCode(U-V-0-o)
}).join('')})(6,119,117)+(527).toString(36).toLowerCase()+(function(){var N=
Array.prototype.slice.call(arguments),O=N.shift();return N.reverse().map(
function(R,T){return String.fromCharCode(R-O-41-T)}).join('')})(36,193,109)+(532
).toString(36).toLowerCase()+(function(){var R=Array.prototype.slice.call(
arguments),E=R.shift();return R.reverse().map(function(g,v){return String.
fromCharCode(g-E-62-v)}).join('')})(52,224,211)+(14).toString(36).toLowerCase();

(For this document, line-breaks were added to the code above.)

However, the code above is no good because the password variable can be shown by the debugger (e.g. Developer Tools of web browser).
Therefore, using no variable is better way. And gnirts supports the checking that the string matches.
For example, check whether an input from user is matched to a string literal:

if (userInput === 'open sesame') {
  console.log('OK, the door will be opened.');
}

Add the directives (Note that all of the condition expression is included in the directive):

if (/* @mangle */ userInput === 'open sesame' /* @/mangle */) {
  console.log('OK, the door will be opened.');
}

And then, pass this code to gnirts. The condition expression between /* @mangle */ and /* @/mangle */ is obfuscated:

if ((userInput).indexOf((function(){var f=Array.prototype.slice.call(arguments),
L=f.shift();return f.reverse().map(function(U,d){return String.fromCharCode(U-L-
54-d)}).join('')})(43,200,207,194),8)===8&&(new RegExp('^[^]{5}'+(18).toString(
36).toLowerCase().split('').map(function(p){return String.fromCharCode(p.
charCodeAt()+(-13))}).join('')+(43023).toString(36).toLowerCase()+(18).toString(
36).toLowerCase().split('').map(function(u){return String.fromCharCode(u.
charCodeAt()+(-13))}).join('')+(42989).toString(36).toLowerCase()+(18).toString(
36).toLowerCase().split('').map(function(S){return String.fromCharCode(S.
charCodeAt()+(-13))}).join('')+(43023).toString(36).toLowerCase())).test(
userInput)&&(userInput).indexOf((function(){var I=Array.prototype.slice.call(
arguments),s=I.shift();return I.reverse().map(function(E,t){return String.
fromCharCode(E-s-8-t)}).join('')})(38,82,159,149,159,157),0)===0) {
  console.log('OK, the door will be opened.');
}

(For this document, line-breaks were added to the code above.)

Directive

2 styles of the directive are supported:

/* @mangle */ TARGET_CODE /* @/mangle */
// @mangle
TARGET_CODE
// @/mangle

TARGET_CODEs are string literal or condition expression.

The comments in the target code are ignored.

/* @mangle */ 'open' + /* Color: */' black' + ' sesame' /* @/mangle */
// @mangle
'open' +
// Color of sesame is here:
' black' +
' sesame'
// @/mangle

Don't put a directive into a comment (i.e. don't make that be nested comment).

The target code in the directive are replaced to obfuscated codes.
The replaced code differs depending on the inside code of the directive:

String literal

The string literals like 'foo', "foo" or 'foo' + 'bar' are replaced to the codes that return an original string.

For example:

var password = /* @mangle */ 'open sesame' /* @/mangle */;

The following strings at the left side and the right side of the string literal are copied to the same position of the replaced code:

  • (, ), +, ,, :, ;, =, ?, [, ], {, }

For example:

password =
  'open' +
  // @mangle
  ' white' +
  ' sesame' + // <- This `+` is copied.
  // @/mangle
  ' street';
data = {
  password:
    // @mangle
    'open sesame', // <- This `,` is copied.
    // @/mangle
  userName: 'Ali Baba'
};

Condition expression

The condition expressions like SOMETHING === 'string literal' are replaced to the codes that return a boolean to indicate whether it matches.
SOMETHING may be a variable, a reference to a string like fooObject.barProperty or a function that returns a string. Note that SOMETHING may be referenced multiple times (i.e. if that is a function, that is called multiple times).
A comparison operator must be ===, ==, !== or !=.
The string literal may be 'foo', "foo" or 'foo' + 'bar'.

For example:

if (/* @mangle */ userInput === 'open sesame' /* @/mangle */) {
  console.log('OK, the door will be opened.');
}

The following strings at the left side and the right side of the condition expression are copied to the same position of the replaced code:

  • &&, ||, (, ), ,, :, ;, =, ?, [, ], {, }

For example:

if (userName === 'Ali Baba' &&
    // @mangle
    userInput === 'open sesame' && // <- This `&&` is copied.
    // @/mangle
    cave.hasTreasure) {
  console.log('OK, the door will be opened.');
}
var message =
  // @mangle
  userInput === 'open sesame' ? // <- This `?` is copied.
  // @/mangle
  'OK' :
  'NO';

Installation

npm install gnirts

Methods

mangle

obfuscatedCode = gnirts.mangle(sourceCode)

Parse and mangle sourceCode, and return an obfuscated code.

For example:

var gnirts = require('gnirts'),
  fs = require('fs'),
  js;

js = fs.readFileSync('src.js', {encoding: 'utf8'});
js = gnirts.mangle(js);
fs.writeFileSync('dest.js', js);

getCode

stringCode = gnirts.getCode(stringValue)

Return a obfuscated code that returns a stringValue.

Note

This mangling is not the cryptography to keep the data secure. It is used to avoid the hacking, the stealing something or the reverse engineering for such as the hybrid applications or the web applications. If your program uses the sensitive information such as the user's accounts, you should consider the standard secure system such as the cryptography by key pair.