Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
Change Log

v0.20.1
---
* Fixed identifier names generations for `mangled` and `dictionary` identifier names generators
* Fixed combination of `identifierNamesGenerator: dictionary` and `debugProtection` options
* `seed` option now accepts `string` and `number` values

v0.20.0
---
* **Breaking:** dropped support of Node 8 because of end of maintenance support
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ Following options are available for the JS Obfuscator:
--reserved-names '<list>' (comma separated)
--reserved-strings '<list>' (comma separated)
--rotate-string-array <boolean>
--seed <number>
--seed <string|number>
--self-defending <boolean>
--source-map <boolean>
--source-map-base-url <string>
Expand Down Expand Up @@ -673,7 +673,7 @@ Shift the `stringArray` array by a fixed and random (generated at the code obfus
This option is recommended if your original source code isn't small, as the helper function can attract attention.

### `seed`
Type: `number` Default: `0`
Type: `string|number` Default: `0`

This option sets seed for random generator. This is useful for creating repeatable results.

Expand Down
8 changes: 4 additions & 4 deletions dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "0.20.0",
"version": "0.20.1",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down
2 changes: 1 addition & 1 deletion src/JavaScriptObfuscator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
const timeStart: number = Date.now();
this.logger.info(LoggingMessage.Version, process.env.VERSION);
this.logger.info(LoggingMessage.ObfuscationStarted);
this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getSeed());
this.logger.info(LoggingMessage.RandomGeneratorSeed, this.randomGenerator.getInputSeed());

// parse AST tree
const astTree: ESTree.Program = this.parseCode(sourceCode);
Expand Down
2 changes: 1 addition & 1 deletion src/cli/JavaScriptObfuscatorCLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
BooleanSanitizer
)
.option(
'--seed <number>',
'--seed <string|number>',
'Sets seed for random generator. This is useful for creating repeatable results.',
parseFloat
)
Expand Down
81 changes: 41 additions & 40 deletions src/container/modules/generators/GeneratorsModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,46 @@ export const generatorsModule: interfaces.ContainerModule = new ContainerModule(
.whenTargetNamed(IdentifierNamesGenerator.MangledIdentifierNamesGenerator);

// identifier name generator factory
function identifierNameGeneratorFactory (): (context: interfaces.Context) => (options: IOptions) => IIdentifierNamesGenerator {
let cachedIdentifierNamesGenerator: IIdentifierNamesGenerator | null = null;

return (context: interfaces.Context): (options: IOptions) => IIdentifierNamesGenerator => (options: IOptions) => {
if (cachedIdentifierNamesGenerator) {
return cachedIdentifierNamesGenerator;
}

let identifierNamesGenerator: IIdentifierNamesGenerator;

switch (options.identifierNamesGenerator) {
case IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
);

break;

case IdentifierNamesGenerator.MangledIdentifierNamesGenerator:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.MangledIdentifierNamesGenerator
);

break;

case IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator:
default:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
);
}

cachedIdentifierNamesGenerator = identifierNamesGenerator;

return identifierNamesGenerator;
};
}
bind<IIdentifierNamesGenerator>(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
.toFactory<IIdentifierNamesGenerator>((context: interfaces.Context): (options: IOptions) => IIdentifierNamesGenerator => {
let cachedIdentifierNamesGenerator: IIdentifierNamesGenerator | null = null;

return (options: IOptions) => {
if (cachedIdentifierNamesGenerator) {
return cachedIdentifierNamesGenerator;
}

let identifierNamesGenerator: IIdentifierNamesGenerator;

switch (options.identifierNamesGenerator) {
case IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
);

break;

case IdentifierNamesGenerator.MangledIdentifierNamesGenerator:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.MangledIdentifierNamesGenerator
);

break;

case IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator:
default:
identifierNamesGenerator = context.container.getNamed<IIdentifierNamesGenerator>(
ServiceIdentifiers.IIdentifierNamesGenerator,
IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator
);
}

cachedIdentifierNamesGenerator = identifierNamesGenerator;

return identifierNamesGenerator;
};
});
.toFactory<IIdentifierNamesGenerator>(identifierNameGeneratorFactory());
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { BlackListObfuscatingGuard } from '../../../node-transformers/preparing-
import { CommentsTransformer } from '../../../node-transformers/preparing-transformers/CommentsTransformer';
import { ConditionalCommentObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ConditionalCommentObfuscatingGuard';
import { CustomNodesTransformer } from '../../../node-transformers/preparing-transformers/CustomNodesTransformer';
import { EvalCallExpressionTransformer } from '../../../node-transformers/preparing-transformers/EvaCallExpressionTransformer';
import { EvalCallExpressionTransformer } from '../../../node-transformers/preparing-transformers/EvalCallExpressionTransformer';
import { MetadataTransformer } from '../../../node-transformers/preparing-transformers/MetadataTransformer';
import { ObfuscatingGuardsTransformer } from '../../../node-transformers/preparing-transformers/ObfuscatingGuardsTransformer';
import { ParentificationTransformer } from '../../../node-transformers/preparing-transformers/ParentificationTransformer';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export class StringArrayCallsWrapper extends AbstractCustomNode {
...NO_ADDITIONAL_NODES_PRESET,
identifierNamesGenerator: this.options.identifierNamesGenerator,
identifiersDictionary: this.options.identifiersDictionary,
seed: this.options.seed
seed: this.randomGenerator.getRawSeed()
}
).getObfuscatedCode();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class StringArrayRotateFunctionNode extends AbstractCustomNode {
...NO_ADDITIONAL_NODES_PRESET,
identifierNamesGenerator: this.options.identifierNamesGenerator,
identifiersDictionary: this.options.identifiersDictionary,
seed: this.options.seed
seed: this.randomGenerator.getRawSeed()
}
).getObfuscatedCode();
}
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/options/IOptions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface IOptions {
readonly reservedNames: string[];
readonly reservedStrings: string[];
readonly rotateStringArray: boolean;
readonly seed: number;
readonly seed: string | number;
readonly selfDefending: boolean;
readonly sourceMap: boolean;
readonly sourceMapBaseUrl: string;
Expand Down
9 changes: 7 additions & 2 deletions src/interfaces/utils/IRandomGenerator.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ export interface IRandomGenerator {
getRandomString (length: number, pool?: string): string;

/**
* @returns {number}
* @returns {string}
*/
getInputSeed (): string;

/**
* @returns {string}
*/
getSeed (): number;
getRawSeed (): string;
}
5 changes: 2 additions & 3 deletions src/options/Options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,9 @@ export class Options implements IOptions {
public readonly rotateStringArray!: boolean;

/**
* @type {number}
* @type {string | number}
*/
@IsNumber()
public readonly seed!: number;
public readonly seed!: string | number;

/**
* @type {boolean}
Expand Down
2 changes: 2 additions & 0 deletions src/options/OptionsNormalizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { DeadCodeInjectionRule } from './normalizer-rules/DeadCodeInjectionRule'
import { DeadCodeInjectionThresholdRule } from './normalizer-rules/DeadCodeInjectionThresholdRule';
import { DomainLockRule } from './normalizer-rules/DomainLockRule';
import { InputFileNameRule } from './normalizer-rules/InputFileNameRule';
import { SeedRule } from './normalizer-rules/SeedRule';
import { SelfDefendingRule } from './normalizer-rules/SelfDefendingRule';
import { SourceMapBaseUrlRule } from './normalizer-rules/SourceMapBaseUrlRule';
import { SourceMapFileNameRule } from './normalizer-rules/SourceMapFileNameRule';
Expand All @@ -29,6 +30,7 @@ export class OptionsNormalizer implements IOptionsNormalizer {
DeadCodeInjectionThresholdRule,
DomainLockRule,
InputFileNameRule,
SeedRule,
SelfDefendingRule,
SourceMapBaseUrlRule,
SourceMapFileNameRule,
Expand Down
25 changes: 25 additions & 0 deletions src/options/normalizer-rules/SeedRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { TOptionsNormalizerRule } from '../../types/options/TOptionsNormalizerRule';

import { IOptions } from '../../interfaces/options/IOptions';

/**
* @param {IOptions} options
* @returns {IOptions}
*/
export const SeedRule: TOptionsNormalizerRule = (options: IOptions): IOptions => {
if (options.seed) {
return {
...options,
seed: options.seed
};
}

const getRandomInteger: (min: number, max: number) => number = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1) + min);
};

return {
...options,
seed: getRandomInteger(0, 999_999_999)
};
};
4 changes: 0 additions & 4 deletions src/storages/string-array/StringArrayStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ export class StringArrayStorage extends ArrayStorage <string> {
public initialize (): void {
super.initialize();

if (!this.options.stringArray) {
return;
}

const baseStringArrayName: string = this.identifierNamesGenerator
.generate(StringArrayStorage.stringArrayNameLength);
const baseStringArrayCallsWrapperName: string = this.identifierNamesGenerator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export function DebugProtectionFunctionCallTemplate (): string {
(function () {
{singleNodeCallControllerFunctionName}(this, function () {
var regExp1 = new RegExp('function *\\\\( *\\\\)');
var regExp2 = new RegExp('\\\\+\\\\+ *\\(?:_0x(?:[a-f0-9]){4,6}|(?:\\\\b|\\\\d)[a-z0-9]{1,4}(?:\\\\b|\\\\d)\\)', 'i');
var regExp2 = new RegExp('\\\\+\\\\+ *\\(?:[a-zA-Z_$][0-9a-zA-Z_$]*\\)', 'i');

var result = {debugProtectionFunctionName}('init');

Expand Down
48 changes: 22 additions & 26 deletions src/utils/RandomGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@ export class RandomGenerator implements IRandomGenerator, IInitializable {
@initializable()
private randomGenerator!: Chance.Chance;

/**
* @type {number}
*/
@initializable()
private seed!: number;

/**
* @type {ISourceCode}
*/
Expand All @@ -54,24 +48,7 @@ export class RandomGenerator implements IRandomGenerator, IInitializable {

@postConstruct()
public initialize (): void {
const getRandomInteger: (min: number, max: number) => number = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1) + min);
};

/**
* We need to add numbers from md5 hash of source code to input seed to prevent same String Array name
* for different bundles with same seed
*
* @returns {number}
*/
const getSeed: () => number = (): number => {
const md5Hash: string = md5(this.sourceCode.getSourceCode());

return this.seed + Number(md5Hash.replace(/\D/g, ''));
};

this.seed = this.options.seed !== 0 ? this.options.seed : getRandomInteger(0, 999_999_999);
this.randomGenerator = new Chance(getSeed());
this.randomGenerator = new Chance(this.getRawSeed());
}

/**
Expand Down Expand Up @@ -110,9 +87,28 @@ export class RandomGenerator implements IRandomGenerator, IInitializable {
}

/**
* @returns {string}
*/
public getInputSeed (): string {
return this.options.seed.toString();
}

/**
* We need to add numbers from md5 hash of source code to input seed to prevent same String Array name
* for different bundles with same seed
*
* @returns {number}
*/
public getSeed (): number {
return this.seed;
public getRawSeed (): string {
const inputSeed: string = this.getInputSeed();
const inputSeedParts: string[] = `${inputSeed}`.split('|');

if (inputSeedParts.length > 1) {
return inputSeed;
}

const sourceCodeMD5Hash: string = md5(this.sourceCode.getSourceCode());

return `${inputSeed}|${sourceCodeMD5Hash}`;
}
}
45 changes: 38 additions & 7 deletions test/dev/dev.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
'use strict';
import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
import { IdentifierNamesGenerator } from '../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';

(function () {
const JavaScriptObfuscator: any = require('../../index');

let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
var abc = 1;
var cde = 1;
var fg = 1;
var sss = 1;
// Paste your JavaScript code here
function hi() {
console.log("Hello World!");
}
hi();
`,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
renameGlobals: true
selfDefending: false,
disableConsoleOutput: false,
debugProtection: false,
debugProtectionInterval: false,
splitStrings: true,
splitStringsChunkLength: 5,
splitStringsChunkLengthEnabled: true,
stringArray: true,
rotateStringArray: false,
rotateStringArrayEnabled: true,
stringArrayThreshold: 1,
stringArrayThresholdEnabled: true,
stringArrayEncoding: false,
stringArrayEncodingEnabled: true,
sourceMap: false,
sourceMapBaseUrl: "",
sourceMapFileName: "",
sourceMapSeparate: false,
domainLock: [],
reservedNames: [],
reservedStrings: [],
seed: 0,
controlFlowFlatteningThreshold: 1,
controlFlowFlattening: true,
deadCodeInjectionThreshold: 1,
deadCodeInjection: true,
unicodeEscapeSequence: false,
renameGlobals: true,
identifierNamesGenerator: IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
identifiersDictionary: ["foo", "bar", "baz", "bark", "hawk", "fooz", "moscow", "chikago"],
identifiersPrefix: "",
transformObjectKeys: true
}
).getObfuscatedCode();

Expand Down
Loading