Writing simple obfuscation and minification system
Tags: node, obfuscate, javascript, security
Published: 2019-09-09 19:56:39

---
title: Writing simple obfuscation and minification system
published: true
description: Tutorial for writing obfusction build system for javascript.
tags: #nodejs #obfuscate #js #security
cover_image: https://images.unsplash.com/photo-1515524738708-327f6b0037a7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80
---

Obfuscation is the process of making your code unclear and unreadable to humans. This adds a level of security to source code specially in web world were source code is readily available. Minification is the process of removing unnecessary data present in code resulting in smaller file sizes and faster loading. In this tutorial we will focus on making a simple build system which detects every javascript file in our source code to obfuscate and minify.

## Prerequisites
To follow this tutorial you need basic knowledge of Javascript and Nodejs. We will use javascript-obfuscator to obfuscate and minify code.

#### Let's go...

### Installation
We will only use one external library [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator) which can be installed as a dev dependency. 

`npm install --save-dev javascript-obfuscator`

### Imports & Folders
In total we need three libraries - fs, path and javascript-obfuscator.
```javascript
const Fs = require('fs');
const Path = require('path');
const JavaScriptObfuscator = require('javascript-obfuscator');
```
The source code will be kept in _src_ folder and final build files will be generated in _build_ folder.
```javascript
const src = Path.join(__dirname, '/src/');
const build = Path.join(__dirname, '/build/');
```

### Read directories
All the directories will be read recursively and find javascript files which will be than obfuscated and minified. To read files we will use fs module.
```javascript
function readDirectory(dirPath)
{
	Fs.readdir(dirPath, (err, files) => 
	{
		if(err)
		{
			console.error("Could not list directory.", err);
			process.exit(1);
		}

		files.forEach((file, index) => // loop through every file
		{
			let path = Path.join(dirPath, file);
			console.log(path);
		});
	});
}
```
This will give us path of every file and folder in the provided directory. But we need to read differentiate between files and directories and further read the directories found. This can be done through `stat` function provided by fs.
```javascript
Fs.stat(path, (err, stat) => 
{
	if(err)
	{
		console.log("error in stating file.", err);
		return;
	}

	if(stat.isFile())
	{
		console.log(`${path} is a file`);
	}
	else if(stat.isDirectory())
	{
		console.log(`${path} is a folder`);
		readDirectory(path); // Further read the folder.
	}
});
```
### Copy files and directories from src to build directory
Now this is perfect time that we start copying all the files found in src to build directory. While copying we will simultaneously also create absent directories present in src.
```javascript
if(stat.isFile())
{
	const newPath = path.replace(src, build); // Replace src path with build path.
	Fs.copyFileSync(path, newPath); // Copy file from old path in src to new path in build.
	if(newPath.endsWith(".js")) // Check if it is javascript file.
	{
		obfuscate(newPath); // Obfuscate copied file in build folder.
	}
}
else if(stat.isDirectory())
{
	var newDir = path.replace(src, build); // Replace src path with build path.
    if (!Fs.existsSync(newDir)) // Check if directory exists or not.
    {
        Fs.mkdirSync(newDir); // Create new directory.
    }
	readDirectory(path); // Further read the folder.
}
```

### Obfuscation and Minification
Finally, javascript file found will be obfuscated and minified. To do so, we will use `JavaScriptObfuscator.obfuscate` function which takes code as first argument and a config object as second.
```javascript
function obfuscate(filePath)
{
	const content = Fs.readFileSync(filePath).toString(); // Read the files content.
	var result = JavaScriptObfuscator.obfuscate(content,
	    { // Config for obfuscation
	        compact: true, // Set true to enable minification
	        controlFlowFlattening: true,
	        target: 'browser'
	    }
	); // Generated minified and obfuscated code

	Fs.writeFileSync(filePath, result.getObfuscatedCode()); // Write obfuscted and minified code generated back to file.
}
```
You can read more about the config options [here](https://github.com/javascript-obfuscator/javascript-obfuscator/#javascript-obfuscator-options).

## Finally...
Here is the full code
```javascript
const Fs = require('fs');
const Path = require('path');
const JavaScriptObfuscator = require('javascript-obfuscator');

const src = Path.join(__dirname, '/src/');
const build = Path.join(__dirname, '/build/');

readDirectory(src); // Start reading with src directory.

function readDirectory(dirPath)
{
	Fs.readdir(dirPath, (err, files) => 
	{
		if(err)
		{
			console.error("Could not list directory.", err);
			process.exit(1);
		}

		files.forEach((file, index) => // loop through every file
		{
			let path = Path.join(dirPath, file);
			
			Fs.stat(path, (err, stat) => 
			{
				if(err)
				{
					console.log("error in stating file.", err);
					return;
				}

				if(stat.isFile())
				{
					const newPath = path.replace(src, build); // Replace src path with build path.
					Fs.copyFileSync(path, newPath); // Copy file from old path in src to new path in build.
					if(newPath.endsWith(".js")) // Check if it is javascript file.
					{
						obfuscate(newPath); // Obfuscate copied file in build folder.
					}
				}
				else if(stat.isDirectory())
				{
					var newDir = path.replace(src, build); // Replace src path with build path.
				    if (!Fs.existsSync(newDir)) // Check if directory exists or not.
				    {
				        Fs.mkdirSync(newDir); // Create new directory.
				    }
					readDirectory(path); // Further read the folder.
				}
			});			
		});
	});
}

function obfuscate(filePath)
{
	const content = Fs.readFileSync(filePath).toString(); // Read the files content.
	var result = JavaScriptObfuscator.obfuscate(content,
	    { // Config for obfuscation
	        compact: true, // Set true to enable minification
	        controlFlowFlattening: true,
	        target: 'browser'
	    }
	); // Generated minified and obfuscated code

	Fs.writeFileSync(filePath, result.getObfuscatedCode()); // Write obfuscted and minified code generated back to file.
}
```

__Hurray!!! you made till end.__ 
I hope you would have found it useful. If yes, than show some love by commenting and sharing.
#####Thanks for reading :)