mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
Mixed string array encoding prototype
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
Change Log
|
||||
|
||||
v2.0.0
|
||||
---
|
||||
* **Breaking change:** `stringArrayEncoding` option now accepts array of encodings. Each string will randomly encoded with available encoding.
|
||||
|
||||
v1.12.0
|
||||
---
|
||||
* **New option:** `optionsPreset` allows to set options preset
|
||||
|
||||
Vendored
+5
-5
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "javascript-obfuscator",
|
||||
"version": "1.12.0",
|
||||
"version": "2.0.0",
|
||||
"description": "JavaScript obfuscator",
|
||||
"keywords": [
|
||||
"obfuscator",
|
||||
|
||||
@@ -337,10 +337,10 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
|
||||
BooleanSanitizer
|
||||
)
|
||||
.option(
|
||||
'--string-array-encoding <string|boolean>',
|
||||
'--string-array-encoding <list> (comma separated, without whitespaces)',
|
||||
'Encodes all strings in strings array using base64 or rc4 (this option can slow down your code speed. ' +
|
||||
'Values: true, false, base64, rc4. ' +
|
||||
'Default: false',
|
||||
'Values: none, base64, rc4. ' +
|
||||
'Default: none',
|
||||
StringArrayEncodingSanitizer
|
||||
)
|
||||
.option(
|
||||
|
||||
@@ -3,21 +3,24 @@ import { TStringArrayEncoding } from '../../types/options/TStringArrayEncoding';
|
||||
|
||||
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
|
||||
|
||||
import { ArraySanitizer } from './ArraySanitizer';
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {TStringArrayEncoding}
|
||||
* @returns {TStringArrayEncoding[]}
|
||||
*/
|
||||
export const StringArrayEncodingSanitizer: TCLISanitizer <TStringArrayEncoding> = (value: string): TStringArrayEncoding => {
|
||||
switch (value) {
|
||||
case 'true':
|
||||
case '1':
|
||||
case StringArrayEncoding.Base64:
|
||||
return true;
|
||||
export const StringArrayEncodingSanitizer: TCLISanitizer <TStringArrayEncoding[]> = (value: string): TStringArrayEncoding[] => {
|
||||
const valuesAsArray: TStringArrayEncoding[] = <TStringArrayEncoding[]>ArraySanitizer(value);
|
||||
|
||||
case StringArrayEncoding.Rc4:
|
||||
return StringArrayEncoding.Rc4;
|
||||
const isCorrectStringArrayEncodings: boolean = valuesAsArray.every((item: TStringArrayEncoding) =>
|
||||
Object
|
||||
.values(StringArrayEncoding)
|
||||
.includes(item)
|
||||
);
|
||||
|
||||
default:
|
||||
return false;
|
||||
if (!isCorrectStringArrayEncodings) {
|
||||
throw new ReferenceError('Invalid value of `--string-array-encoding` option');
|
||||
}
|
||||
|
||||
return valuesAsArray;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
||||
|
||||
import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
|
||||
import { TStatement } from '../../types/node/TStatement';
|
||||
import { TStringArrayEncoding } from '../../types/options/TStringArrayEncoding';
|
||||
|
||||
import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
|
||||
import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
|
||||
@@ -44,6 +45,12 @@ export class StringArrayCallsWrapperCodeHelper extends AbstractCustomCodeHelper
|
||||
@initializable()
|
||||
private stringArrayCallsWrapperName!: string;
|
||||
|
||||
/**
|
||||
* @type {TStringArrayEncoding}
|
||||
*/
|
||||
@initializable()
|
||||
private stringArrayEncoding!: TStringArrayEncoding;
|
||||
|
||||
/**
|
||||
* @type {IEscapeSequenceEncoder}
|
||||
*/
|
||||
@@ -80,15 +87,18 @@ export class StringArrayCallsWrapperCodeHelper extends AbstractCustomCodeHelper
|
||||
/**
|
||||
* @param {string} stringArrayName
|
||||
* @param {string} stringArrayCallsWrapperName
|
||||
* @param {TStringArrayEncoding} stringArrayEncoding
|
||||
* @param {string} atobFunctionName
|
||||
*/
|
||||
public initialize (
|
||||
stringArrayName: string,
|
||||
stringArrayCallsWrapperName: string,
|
||||
stringArrayEncoding: TStringArrayEncoding,
|
||||
atobFunctionName: string
|
||||
): void {
|
||||
this.stringArrayName = stringArrayName;
|
||||
this.stringArrayCallsWrapperName = stringArrayCallsWrapperName;
|
||||
this.stringArrayEncoding = stringArrayEncoding;
|
||||
this.atobFunctionName = atobFunctionName;
|
||||
}
|
||||
|
||||
@@ -147,7 +157,7 @@ export class StringArrayCallsWrapperCodeHelper extends AbstractCustomCodeHelper
|
||||
);
|
||||
}
|
||||
|
||||
switch (this.options.stringArrayEncoding) {
|
||||
switch (this.stringArrayEncoding) {
|
||||
case StringArrayEncoding.Rc4:
|
||||
decodeStringArrayTemplate = this.customCodeHelperFormatter.formatTemplate(
|
||||
StringArrayRC4DecodeTemplate(this.randomGenerator),
|
||||
|
||||
@@ -85,12 +85,14 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
|
||||
);
|
||||
|
||||
// stringArrayCallsWrapper helper nodes append
|
||||
this.appendCustomNodeIfExist(
|
||||
CustomCodeHelper.StringArrayCallsWrapper,
|
||||
(customCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>>) => {
|
||||
NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), 1);
|
||||
}
|
||||
);
|
||||
for (const stringArrayEncoding of this.options.stringArrayEncoding) {
|
||||
this.appendCustomNodeIfExist(
|
||||
<any>`${CustomCodeHelper.StringArrayCallsWrapper}-${stringArrayEncoding}`,
|
||||
(customCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>>) => {
|
||||
NodeAppender.insertAtIndex(nodeWithStatements, customCodeHelper.getNode(), 1);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// stringArrayRotateFunction helper nodes append
|
||||
this.appendCustomNodeIfExist(
|
||||
@@ -108,24 +110,44 @@ export class StringArrayCodeHelperGroup extends AbstractCustomCodeHelperGroup {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stage 1: String Array code helper
|
||||
*/
|
||||
const stringArrayCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCodeHelper>> =
|
||||
this.customCodeHelperFactory(CustomCodeHelper.StringArray);
|
||||
const stringArrayCallsWrapperCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>> =
|
||||
this.customCodeHelperFactory(CustomCodeHelper.StringArrayCallsWrapper);
|
||||
const stringArrayRotateFunctionCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>> =
|
||||
this.customCodeHelperFactory(CustomCodeHelper.StringArrayRotateFunction);
|
||||
|
||||
const stringArrayName: string = this.stringArrayStorage.getStorageName();
|
||||
const stringArrayCallsWrapperName: string = this.stringArrayStorage.getStorageCallsWrapperName();
|
||||
const stringArrayRotationAmount: number = this.stringArrayStorage.getRotationAmount();
|
||||
const atobFunctionName: string = this.randomGenerator.getRandomString(6);
|
||||
|
||||
stringArrayCodeHelper.initialize(this.stringArrayStorage, stringArrayName);
|
||||
stringArrayCallsWrapperCodeHelper.initialize(stringArrayName, stringArrayCallsWrapperName, atobFunctionName);
|
||||
stringArrayRotateFunctionCodeHelper.initialize(stringArrayName, stringArrayRotationAmount);
|
||||
|
||||
this.customCodeHelpers.set(CustomCodeHelper.StringArray, stringArrayCodeHelper);
|
||||
this.customCodeHelpers.set(CustomCodeHelper.StringArrayCallsWrapper, stringArrayCallsWrapperCodeHelper);
|
||||
|
||||
/**
|
||||
* Stage 2: String Array calls wrapper code helper
|
||||
*/
|
||||
const atobFunctionName: string = this.randomGenerator.getRandomString(6);
|
||||
|
||||
for (const stringArrayEncoding of this.options.stringArrayEncoding) {
|
||||
const stringArrayCallsWrapperCodeHelper: ICustomCodeHelper<TInitialData<StringArrayCallsWrapperCodeHelper>> =
|
||||
this.customCodeHelperFactory(CustomCodeHelper.StringArrayCallsWrapper);
|
||||
const stringArrayCallsWrapperName: string = this.stringArrayStorage.getStorageCallsWrapperName(stringArrayEncoding);
|
||||
|
||||
stringArrayCallsWrapperCodeHelper.initialize(
|
||||
stringArrayName,
|
||||
stringArrayCallsWrapperName,
|
||||
stringArrayEncoding,
|
||||
atobFunctionName
|
||||
);
|
||||
|
||||
this.customCodeHelpers.set(<any>`${CustomCodeHelper.StringArrayCallsWrapper}-${stringArrayEncoding}`, stringArrayCallsWrapperCodeHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stage 3: String Array rotate function
|
||||
*/
|
||||
const stringArrayRotateFunctionCodeHelper: ICustomCodeHelper<TInitialData<StringArrayRotateFunctionCodeHelper>> =
|
||||
this.customCodeHelperFactory(CustomCodeHelper.StringArrayRotateFunction);
|
||||
const stringArrayRotationAmount: number = this.stringArrayStorage.getRotationAmount();
|
||||
|
||||
stringArrayRotateFunctionCodeHelper.initialize(stringArrayName, stringArrayRotationAmount);
|
||||
|
||||
if (this.options.rotateStringArray) {
|
||||
this.customCodeHelpers.set(CustomCodeHelper.StringArrayRotateFunction, stringArrayRotateFunctionCodeHelper);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { MakeEnum } from '@gradecam/tsenum';
|
||||
|
||||
export const StringArrayEncoding: Readonly<{
|
||||
None: 'none';
|
||||
Base64: 'base64';
|
||||
Rc4: 'rc4';
|
||||
}> = MakeEnum({
|
||||
None: 'none',
|
||||
Base64: 'base64',
|
||||
Rc4: 'rc4'
|
||||
});
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { TStringArrayEncoding } from '../types/options/TStringArrayEncoding';
|
||||
|
||||
export interface IEncodedValue {
|
||||
encoding: TStringArrayEncoding | null;
|
||||
encodedValue: string;
|
||||
decodeKey: string | null;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export interface IOptions {
|
||||
readonly splitStrings: boolean;
|
||||
readonly splitStringsChunkLength: number;
|
||||
readonly stringArray: boolean;
|
||||
readonly stringArrayEncoding: TStringArrayEncoding;
|
||||
readonly stringArrayEncoding: TStringArrayEncoding[];
|
||||
readonly stringArrayThreshold: number;
|
||||
readonly target: TypeFromEnum<typeof ObfuscationTarget>;
|
||||
readonly transformObjectKeys: boolean;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { IStringArrayStorageItemData } from './IStringArrayStorageItem';
|
||||
import { TStringArrayEncoding } from '../../../types/options/TStringArrayEncoding';
|
||||
|
||||
import { IMapStorage } from '../IMapStorage';
|
||||
import { IStringArrayStorageItemData } from './IStringArrayStorageItem';
|
||||
|
||||
export interface IStringArrayStorage extends IMapStorage <string, IStringArrayStorageItemData> {
|
||||
/**
|
||||
@@ -14,9 +15,10 @@ export interface IStringArrayStorage extends IMapStorage <string, IStringArraySt
|
||||
getStorageName (): string;
|
||||
|
||||
/**
|
||||
* @param {TStringArrayEncoding | null} stringArrayEncoding
|
||||
* @returns {string}
|
||||
*/
|
||||
getStorageCallsWrapperName (): string;
|
||||
getStorageCallsWrapperName (stringArrayEncoding: TStringArrayEncoding | null): string;
|
||||
|
||||
rotateStorage (): void;
|
||||
|
||||
|
||||
@@ -152,7 +152,8 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
|
||||
const stringArrayStorageItemData: IStringArrayStorageItemData | undefined = this.stringArrayStorageAnalyzer
|
||||
.getItemDataForLiteralNode(literalNode);
|
||||
const cacheKey: string = `${literalValue}-${Boolean(stringArrayStorageItemData)}`;
|
||||
const useCachedValue: boolean = this.nodesCache.has(cacheKey) && this.options.stringArrayEncoding !== StringArrayEncoding.Rc4;
|
||||
const useCachedValue: boolean = this.nodesCache.has(cacheKey)
|
||||
&& stringArrayStorageItemData?.encoding !== StringArrayEncoding.Rc4;
|
||||
|
||||
if (useCachedValue) {
|
||||
return <ESTree.Node>this.nodesCache.get(cacheKey);
|
||||
@@ -182,7 +183,7 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
|
||||
* @returns {Node}
|
||||
*/
|
||||
private getStringArrayCallNode (stringArrayStorageItemData: IStringArrayStorageItemData): ESTree.Node {
|
||||
const { index, decodeKey } = stringArrayStorageItemData;
|
||||
const { index, encoding, decodeKey } = stringArrayStorageItemData;
|
||||
|
||||
const hexadecimalIndex: string = NumberUtils.toHex(index);
|
||||
const callExpressionArgs: (ESTree.Expression | ESTree.SpreadElement)[] = [
|
||||
@@ -194,7 +195,7 @@ export class StringArrayTransformer extends AbstractNodeTransformer {
|
||||
}
|
||||
|
||||
const stringArrayIdentifierNode: ESTree.Identifier = NodeFactory.identifierNode(
|
||||
this.stringArrayStorage.getStorageCallsWrapperName()
|
||||
this.stringArrayStorage.getStorageCallsWrapperName(encoding)
|
||||
);
|
||||
|
||||
return NodeFactory.callExpressionNode(
|
||||
|
||||
@@ -30,7 +30,6 @@ import { IdentifierNamesGenerator } from '../enums/generators/identifier-names-g
|
||||
import { ObfuscationTarget } from '../enums/ObfuscationTarget';
|
||||
import { OptionsPreset } from '../enums/options/presets/OptionsPreset';
|
||||
import { SourceMapMode } from '../enums/source-map/SourceMapMode';
|
||||
import { StringArrayEncoding } from '../enums/StringArrayEncoding';
|
||||
|
||||
import { DEFAULT_PRESET } from './presets/Default';
|
||||
import { LOW_OBFUSCATION_PRESET } from './presets/LowObfuscation';
|
||||
@@ -289,10 +288,14 @@ export class Options implements IOptions {
|
||||
public readonly stringArray!: boolean;
|
||||
|
||||
/**
|
||||
* @type {TStringArrayEncoding}
|
||||
* @type {TStringArrayEncoding[]}
|
||||
*/
|
||||
@IsIn([true, false, StringArrayEncoding.Base64, StringArrayEncoding.Rc4])
|
||||
public readonly stringArrayEncoding!: TStringArrayEncoding;
|
||||
@IsArray()
|
||||
@ArrayUnique()
|
||||
@IsString({
|
||||
each: true
|
||||
})
|
||||
public readonly stringArrayEncoding!: TStringArrayEncoding[];
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
|
||||
@@ -9,12 +9,14 @@ import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
|
||||
* @returns {IOptions}
|
||||
*/
|
||||
export const StringArrayEncodingRule: TOptionsNormalizerRule = (options: IOptions): IOptions => {
|
||||
if (options.stringArrayEncoding === true) {
|
||||
if (!options.stringArrayEncoding.length) {
|
||||
options = {
|
||||
...options,
|
||||
stringArrayEncoding: StringArrayEncoding.Base64
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@ import { TOptionsNormalizerRule } from '../../types/options/TOptionsNormalizerRu
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
|
||||
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
|
||||
|
||||
/**
|
||||
* @param {IOptions} options
|
||||
* @returns {IOptions}
|
||||
@@ -13,7 +15,9 @@ export const StringArrayRule: TOptionsNormalizerRule = (options: IOptions): IOpt
|
||||
rotateStringArray: false,
|
||||
shuffleStringArray: false,
|
||||
stringArray: false,
|
||||
stringArrayEncoding: false,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None
|
||||
],
|
||||
stringArrayThreshold: 0
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import { TOptionsNormalizerRule } from '../../types/options/TOptionsNormalizerRu
|
||||
|
||||
import { IOptions } from '../../interfaces/options/IOptions';
|
||||
|
||||
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
|
||||
|
||||
/**
|
||||
* @param {IOptions} options
|
||||
* @returns {IOptions}
|
||||
@@ -12,7 +14,9 @@ export const StringArrayThresholdRule: TOptionsNormalizerRule = (options: IOptio
|
||||
...options,
|
||||
rotateStringArray: false,
|
||||
stringArray: false,
|
||||
stringArrayEncoding: false,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None
|
||||
],
|
||||
stringArrayThreshold: 0
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { IdentifierNamesGenerator } from '../../enums/generators/identifier-name
|
||||
import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
|
||||
import { OptionsPreset } from '../../enums/options/presets/OptionsPreset';
|
||||
import { SourceMapMode } from '../../enums/source-map/SourceMapMode';
|
||||
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
|
||||
|
||||
export const DEFAULT_PRESET: TInputOptions = Object.freeze({
|
||||
compact: true,
|
||||
@@ -40,7 +41,9 @@ export const DEFAULT_PRESET: TInputOptions = Object.freeze({
|
||||
splitStrings: false,
|
||||
splitStringsChunkLength: 10,
|
||||
stringArray: true,
|
||||
stringArrayEncoding: false,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None
|
||||
],
|
||||
stringArrayThreshold: 0.75,
|
||||
target: ObfuscationTarget.Browser,
|
||||
transformObjectKeys: false,
|
||||
|
||||
@@ -13,6 +13,8 @@ export const HIGH_OBFUSCATION_PRESET: TInputOptions = Object.freeze({
|
||||
debugProtectionInterval: true,
|
||||
optionsPreset: OptionsPreset.HighObfuscation,
|
||||
splitStringsChunkLength: 5,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.Rc4
|
||||
],
|
||||
stringArrayThreshold: 1
|
||||
});
|
||||
|
||||
@@ -13,6 +13,8 @@ export const MEDIUM_OBFUSCATION_PRESET: TInputOptions = Object.freeze({
|
||||
optionsPreset: OptionsPreset.MediumObfuscation,
|
||||
splitStrings: true,
|
||||
splitStringsChunkLength: 10,
|
||||
stringArrayEncoding: StringArrayEncoding.Base64,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.Base64
|
||||
],
|
||||
transformObjectKeys: true
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { TInputOptions } from '../../types/options/TInputOptions';
|
||||
import { IdentifierNamesGenerator } from '../../enums/generators/identifier-names-generators/IdentifierNamesGenerator';
|
||||
import { ObfuscationTarget } from '../../enums/ObfuscationTarget';
|
||||
import { SourceMapMode } from '../../enums/source-map/SourceMapMode';
|
||||
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
|
||||
|
||||
export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
|
||||
compact: true,
|
||||
@@ -37,7 +38,9 @@ export const NO_ADDITIONAL_NODES_PRESET: TInputOptions = Object.freeze({
|
||||
splitStrings: false,
|
||||
splitStringsChunkLength: 0,
|
||||
stringArray: false,
|
||||
stringArrayEncoding: false,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None
|
||||
],
|
||||
stringArrayThreshold: 0,
|
||||
target: ObfuscationTarget.Browser,
|
||||
transformObjectKeys: false,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { inject, injectable, postConstruct } from 'inversify';
|
||||
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
|
||||
|
||||
import { TStringArrayEncoding } from '../../types/options/TStringArrayEncoding';
|
||||
|
||||
import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
|
||||
import { IIdentifierNamesGenerator } from '../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
|
||||
|
||||
@@ -85,9 +87,9 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
|
||||
private stringArrayStorageName!: string;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
* @type {Map<TStringArrayEncoding | null, string>}
|
||||
*/
|
||||
private stringArrayStorageCallsWrapperName!: string;
|
||||
private readonly stringArrayStorageCallsWrapperNamesMap: Map<TStringArrayEncoding | null, string> = new Map();
|
||||
|
||||
/**
|
||||
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
|
||||
@@ -136,7 +138,6 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
|
||||
|
||||
/**
|
||||
* @param {string} value
|
||||
* @returns {IStringArrayStorageItemData}
|
||||
*/
|
||||
public get (value: string): IStringArrayStorageItemData {
|
||||
return this.getOrSetIfDoesNotExist(value);
|
||||
@@ -169,15 +170,25 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TStringArrayEncoding | null} stringArrayEncoding
|
||||
* @returns {string}
|
||||
*/
|
||||
public getStorageCallsWrapperName (): string {
|
||||
if (!this.stringArrayStorageCallsWrapperName) {
|
||||
this.stringArrayStorageCallsWrapperName = this.identifierNamesGenerator
|
||||
.generateForGlobalScope(StringArrayStorage.stringArrayNameLength);
|
||||
public getStorageCallsWrapperName (stringArrayEncoding: TStringArrayEncoding | null): string {
|
||||
const storageCallsWrapperName: string | null = this.stringArrayStorageCallsWrapperNamesMap.get(stringArrayEncoding) ?? null;
|
||||
|
||||
if (storageCallsWrapperName) {
|
||||
return storageCallsWrapperName;
|
||||
}
|
||||
|
||||
return this.stringArrayStorageCallsWrapperName;
|
||||
const newStorageCallsWrapperName: string = this.identifierNamesGenerator
|
||||
.generateForGlobalScope(StringArrayStorage.stringArrayNameLength);
|
||||
|
||||
this.stringArrayStorageCallsWrapperNamesMap.set(
|
||||
stringArrayEncoding,
|
||||
newStorageCallsWrapperName
|
||||
);
|
||||
|
||||
return newStorageCallsWrapperName;
|
||||
}
|
||||
|
||||
public rotateStorage (): void {
|
||||
@@ -234,7 +245,7 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
|
||||
* @returns {IStringArrayStorageItemData}
|
||||
*/
|
||||
private getOrSetIfDoesNotExist (value: string): IStringArrayStorageItemData {
|
||||
const { encodedValue, decodeKey }: IEncodedValue = this.getEncodedValue(value);
|
||||
const { encodedValue, encoding, decodeKey }: IEncodedValue = this.getEncodedValue(value);
|
||||
const storedStringArrayStorageItemData: IStringArrayStorageItemData | undefined = this.storage.get(encodedValue);
|
||||
|
||||
if (storedStringArrayStorageItemData) {
|
||||
@@ -243,6 +254,7 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
|
||||
|
||||
const stringArrayStorageItemData: IStringArrayStorageItemData = {
|
||||
encodedValue,
|
||||
encoding,
|
||||
decodeKey,
|
||||
value,
|
||||
index: this.getLength()
|
||||
@@ -258,7 +270,13 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
|
||||
* @returns {IEncodedValue}
|
||||
*/
|
||||
private getEncodedValue (value: string): IEncodedValue {
|
||||
switch (this.options.stringArrayEncoding) {
|
||||
const encoding: TStringArrayEncoding | null = this.options.stringArrayEncoding.length
|
||||
? this.randomGenerator
|
||||
.getRandomGenerator()
|
||||
.pickone(this.options.stringArrayEncoding)
|
||||
: null;
|
||||
|
||||
switch (encoding) {
|
||||
/**
|
||||
* For rc4 there is a possible chance of a collision between encoded values that were received from
|
||||
* different source values with different keys
|
||||
@@ -293,21 +311,21 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
|
||||
return this.getEncodedValue(value);
|
||||
}
|
||||
|
||||
return { encodedValue, decodeKey };
|
||||
return { encodedValue, encoding, decodeKey };
|
||||
}
|
||||
|
||||
case StringArrayEncoding.Base64: {
|
||||
const decodeKey: null = null;
|
||||
const encodedValue: string = this.cryptUtilsSwappedAlphabet.btoa(value);
|
||||
|
||||
return { encodedValue, decodeKey };
|
||||
return { encodedValue, encoding, decodeKey };
|
||||
}
|
||||
|
||||
default: {
|
||||
const decodeKey: null = null;
|
||||
const encodedValue: string = value;
|
||||
|
||||
return { encodedValue, decodeKey };
|
||||
return { encodedValue, encoding, decodeKey };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@ import { TypeFromEnum } from '@gradecam/tsenum';
|
||||
|
||||
import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
|
||||
|
||||
export type TStringArrayEncoding = boolean | TypeFromEnum<typeof StringArrayEncoding>;
|
||||
export type TStringArrayEncoding = TypeFromEnum<typeof StringArrayEncoding>;
|
||||
|
||||
+14
-9
@@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import { StringArrayEncoding } from '../../src/enums/StringArrayEncoding';
|
||||
|
||||
import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNodes';
|
||||
|
||||
(function () {
|
||||
@@ -7,20 +9,23 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
function func () {
|
||||
var obj = {foo: 'bar'};
|
||||
|
||||
console.log(obj.foo);
|
||||
}
|
||||
var string1 = 'foo';
|
||||
var string2 = 'bar';
|
||||
var string3 = 'baz';
|
||||
var string4 = 'bark';
|
||||
|
||||
func();
|
||||
console.log(string1, string2, string3, string4);
|
||||
`,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
compact: false,
|
||||
transformObjectKeys: true,
|
||||
controlFlowFlattening: true,
|
||||
controlFlowFlatteningThreshold: 1
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.Rc4,
|
||||
StringArrayEncoding.Base64,
|
||||
StringArrayEncoding.None
|
||||
]
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ describe('StringArrayCallsWrapperCodeHelper', () => {
|
||||
identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1,
|
||||
stringArrayEncoding: StringArrayEncoding.Base64
|
||||
stringArrayEncoding: [StringArrayEncoding.Base64]
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
@@ -841,7 +841,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
renameProperties: true,
|
||||
rotateStringArray: true,
|
||||
stringArray: true,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4,
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4],
|
||||
stringArrayThreshold: 1,
|
||||
transformObjectKeys: true,
|
||||
unicodeEscapeSequence: false
|
||||
@@ -932,7 +932,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
...baseParams,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4]
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
@@ -955,7 +955,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
...baseParams,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4]
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
@@ -977,7 +977,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
...baseParams,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4]
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
@@ -1000,7 +1000,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
...baseParams,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4]
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
@@ -1022,7 +1022,7 @@ describe('JavaScriptObfuscator', () => {
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
...baseParams,
|
||||
stringArrayEncoding: StringArrayEncoding.Base64
|
||||
stringArrayEncoding: [StringArrayEncoding.Base64]
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
|
||||
+3
-3
@@ -199,7 +199,7 @@ describe('StringArrayTransformer', () => {
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
stringArray: true,
|
||||
stringArrayEncoding: StringArrayEncoding.Base64,
|
||||
stringArrayEncoding: [StringArrayEncoding.Base64],
|
||||
stringArrayThreshold: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
@@ -228,7 +228,7 @@ describe('StringArrayTransformer', () => {
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
stringArray: true,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4,
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4],
|
||||
stringArrayThreshold: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
@@ -257,7 +257,7 @@ describe('StringArrayTransformer', () => {
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
seed: 1, // set seed to prevent rare case when all encoded values are the same
|
||||
stringArray: true,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4,
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4],
|
||||
stringArrayThreshold: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
@@ -543,7 +543,7 @@ describe('OptionsNormalizer', () => {
|
||||
...getDefaultOptions(),
|
||||
shuffleStringArray: true,
|
||||
stringArray: false,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4,
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4],
|
||||
stringArrayThreshold: 0.5,
|
||||
rotateStringArray: true
|
||||
});
|
||||
@@ -552,7 +552,7 @@ describe('OptionsNormalizer', () => {
|
||||
...getDefaultOptions(),
|
||||
shuffleStringArray: false,
|
||||
stringArray: false,
|
||||
stringArrayEncoding: false,
|
||||
stringArrayEncoding: [StringArrayEncoding.None],
|
||||
stringArrayThreshold: 0,
|
||||
rotateStringArray: false
|
||||
};
|
||||
@@ -567,12 +567,14 @@ describe('OptionsNormalizer', () => {
|
||||
before(() => {
|
||||
optionsPreset = getNormalizedOptions({
|
||||
...getDefaultOptions(),
|
||||
stringArrayEncoding: true
|
||||
stringArrayEncoding: []
|
||||
});
|
||||
|
||||
expectedOptionsPreset = {
|
||||
...getDefaultOptions(),
|
||||
stringArrayEncoding: StringArrayEncoding.Base64
|
||||
stringArrayEncoding: [
|
||||
StringArrayEncoding.None
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import { assert } from 'chai';
|
||||
|
||||
import { readFileAsString } from '../helpers/readFileAsString';
|
||||
|
||||
import { StringArrayEncoding } from '../../src/enums/StringArrayEncoding';
|
||||
|
||||
import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscatorFacade';
|
||||
|
||||
const heapValueToMB = (value: number) => Math.round(value / 1024 / 1024 * 100) / 100;
|
||||
@@ -41,7 +43,7 @@ describe('JavaScriptObfuscator memory', function () {
|
||||
splitStrings: true,
|
||||
splitStringsChunkLength: 2,
|
||||
stringArray: true,
|
||||
stringArrayEncoding: 'base64',
|
||||
stringArrayEncoding: [StringArrayEncoding.Base64],
|
||||
stringArrayThreshold: 0.75,
|
||||
transformObjectKeys: true,
|
||||
unicodeEscapeSequence: false
|
||||
|
||||
@@ -34,7 +34,7 @@ describe('JavaScriptObfuscator runtime eval', function () {
|
||||
splitStrings: true,
|
||||
splitStringsChunkLength: 5,
|
||||
stringArray: true,
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4,
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4],
|
||||
stringArrayThreshold: 1,
|
||||
transformObjectKeys: true,
|
||||
unicodeEscapeSequence: true
|
||||
|
||||
+9
@@ -11,6 +11,8 @@ import { IInversifyContainerFacade } from '../../../../src/interfaces/container/
|
||||
import { IStringArrayStorageAnalyzer } from '../../../../src/interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
|
||||
import { IStringArrayStorageItemData } from '../../../../src/interfaces/storages/string-array-storage/IStringArrayStorageItem';
|
||||
|
||||
import { StringArrayEncoding } from '../../../../src/enums/StringArrayEncoding';
|
||||
|
||||
import { InversifyContainerFacade } from '../../../../src/container/InversifyContainerFacade';
|
||||
import { NodeFactory } from '../../../../src/node/NodeFactory';
|
||||
import { NodeMetadata } from '../../../../src/node/NodeMetadata';
|
||||
@@ -34,12 +36,14 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
|
||||
const expectedStringArrayStorageItemData1: IStringArrayStorageItemData = {
|
||||
encodedValue: 'foo',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'foo'
|
||||
};
|
||||
const expectedStringArrayStorageItemData2: IStringArrayStorageItemData = {
|
||||
encodedValue: 'bar',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 1,
|
||||
value: 'bar'
|
||||
@@ -85,6 +89,7 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
|
||||
const expectedStringArrayStorageItemData1: IStringArrayStorageItemData = {
|
||||
encodedValue: 'foo',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'foo'
|
||||
@@ -124,6 +129,7 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
|
||||
const expectedStringArrayStorageItemData1: IStringArrayStorageItemData = {
|
||||
encodedValue: 'foo',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'foo'
|
||||
@@ -163,6 +169,7 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
|
||||
const expectedStringArrayStorageItemData1: IStringArrayStorageItemData = {
|
||||
encodedValue: 'foo',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'foo'
|
||||
@@ -213,6 +220,7 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
|
||||
const expectedStringArrayStorageItemData1: IStringArrayStorageItemData = {
|
||||
encodedValue: 'foo',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'foo'
|
||||
@@ -330,6 +338,7 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
const expectedStringArrayStorageItemData1: undefined = undefined;
|
||||
const expectedStringArrayStorageItemData2: IStringArrayStorageItemData = {
|
||||
encodedValue: 'bar',
|
||||
encoding: StringArrayEncoding.None,
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'bar'
|
||||
|
||||
@@ -9,76 +9,62 @@ import { StringArrayEncodingSanitizer } from '../../../../src/cli/sanitizers/Str
|
||||
describe('StringArrayEncodingSanitizer', () => {
|
||||
describe('Variant #1: string array encoding `base64`', () => {
|
||||
const inputValue: string = 'base64';
|
||||
const expectedValue: TStringArrayEncoding = true;
|
||||
const expectedValue: TStringArrayEncoding[] = [StringArrayEncoding.Base64];
|
||||
|
||||
let value: TStringArrayEncoding;
|
||||
let value: TStringArrayEncoding[];
|
||||
|
||||
before(() => {
|
||||
value = StringArrayEncodingSanitizer(inputValue);
|
||||
});
|
||||
|
||||
it('should sanitize value', () => {
|
||||
assert.equal(value, expectedValue);
|
||||
assert.deepEqual(value, expectedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: string array encoding `true`', () => {
|
||||
const inputValue: string = 'true';
|
||||
const expectedValue: TStringArrayEncoding = true;
|
||||
describe('Variant #2: string array encoding `base64, rc4`', () => {
|
||||
const inputValue: string = 'base64,rc4';
|
||||
const expectedValue: TStringArrayEncoding[] = [
|
||||
StringArrayEncoding.Base64,
|
||||
StringArrayEncoding.Rc4
|
||||
];
|
||||
|
||||
let value: TStringArrayEncoding;
|
||||
let value: TStringArrayEncoding[];
|
||||
|
||||
before(() => {
|
||||
value = StringArrayEncodingSanitizer(inputValue);
|
||||
});
|
||||
|
||||
it('should sanitize value', () => {
|
||||
assert.equal(value, expectedValue);
|
||||
assert.deepEqual(value, expectedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: string array encoding `1`', () => {
|
||||
const inputValue: string = '1';
|
||||
const expectedValue: TStringArrayEncoding = true;
|
||||
|
||||
let value: TStringArrayEncoding;
|
||||
|
||||
before(() => {
|
||||
value = StringArrayEncodingSanitizer(inputValue);
|
||||
});
|
||||
|
||||
it('should sanitize value', () => {
|
||||
assert.equal(value, expectedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: string array encoding `rc4`', () => {
|
||||
const inputValue: string = 'rc4';
|
||||
const expectedValue: TStringArrayEncoding = StringArrayEncoding.Rc4;
|
||||
|
||||
let value: TStringArrayEncoding;
|
||||
|
||||
before(() => {
|
||||
value = StringArrayEncodingSanitizer(inputValue);
|
||||
});
|
||||
|
||||
it('should sanitize value', () => {
|
||||
assert.equal(value, expectedValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #5: string array encoding `foo`', () => {
|
||||
describe('Variant #3: string array encoding `foo`', () => {
|
||||
const inputValue: string = 'foo';
|
||||
const expectedValue: TStringArrayEncoding = false;
|
||||
|
||||
let value: TStringArrayEncoding;
|
||||
let testFunc: () => TStringArrayEncoding[];
|
||||
|
||||
before(() => {
|
||||
value = StringArrayEncodingSanitizer(inputValue);
|
||||
testFunc = () => StringArrayEncodingSanitizer(inputValue);
|
||||
});
|
||||
|
||||
it('should sanitize value', () => {
|
||||
assert.equal(value, expectedValue);
|
||||
it('should throw an error for invalid encoding', () => {
|
||||
assert.throws(testFunc, 'Invalid value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: string array encoding `base64,foo`', () => {
|
||||
const inputValue: string = 'base64,foo';
|
||||
|
||||
let testFunc: () => TStringArrayEncoding[];
|
||||
|
||||
before(() => {
|
||||
testFunc = () => StringArrayEncodingSanitizer(inputValue);
|
||||
});
|
||||
|
||||
it('should throw an error for invalid encoding', () => {
|
||||
assert.throws(testFunc, 'Invalid value');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ describe('StringArrayStorage', () => {
|
||||
|
||||
before(() => {
|
||||
const stringArrayStorage: IStringArrayStorage = getStorageInstance({
|
||||
stringArrayEncoding: StringArrayEncoding.Rc4
|
||||
stringArrayEncoding: [StringArrayEncoding.Rc4]
|
||||
});
|
||||
|
||||
for (let i = 0; i < samplesCount; i++) {
|
||||
|
||||
Reference in New Issue
Block a user