Skip to content

4th-ATechnologies/s4js

Repository files navigation

This is a wrapper for the S4 encryption library:

S4 is a modern crypto library which focuses on making API's that are easy to use. It can be cross compiled to multiple targets, including to WebAssembly for use in a browser.

To make things easy for developers, a pre-compiled version of S4 is included with the project. The exact commit that was compiled is referenced by commit hash in the filename. See the wasm folder for more info.


Installation

$ npm install s4js

Setup - intro

Using WebAssembly means jumping through a few hoops. As this technology becomes more mainstream, the recommended practices will evolve, and become simpler. For now, here's what I recommend:

The S4 library was compiled using emscripten, and outputs 2 files:

  • libS4.wasm
  • libS4.js

The wasm file is the compiled WebAssembly code. And the libS4.js file was automatically generated by emscripten, and contains the logic to load the wasm file. This logic supports both the browser & Node.js. In other words, you don't have load the wasm file manually. Instead you load the libS4.js file, and it handles loading the wasm for you.

  • Place the libS4.wasm & libS4.js files in the same directory.

Now when you load libS4.js it will create an object in the GLOBAL scope named ModuleS4. If there is already an object in the global scope named ModuleS4, then libS4.js will use it. This gives us various hooks to discover when the wasm file has been loaded, and is ready for us to use.

Setup - browser

Add something like this to your HTML:

<script type="text/javascript">
	var onModuleS4Initialized = [];
	var ModuleS4 = {
		isRuntimeInitialized: false,
		onRuntimeInitialized: function() {
			console.log("WASM: ModuleS4.onRuntimeInitialized()");
				
			ModuleS4.isRuntimeInitialized = true;
			try
			{
				for (var i = 0; i < onModuleS4Initialized.length; i++)
				{
					var listener = onModuleS4Initialized[i];
					listener();
				}
			}
			catch (e) {
				console.error("Exception while attempting to invoke listeners in onModuleS4Initialized array: "+ e);
			}
		},
		print: function(text) {
			console.log("WASM [log]: "+ text);
		},
		printErr: function(text) {
			console.error("WASM [err]: "+ text);
		}
	};
</script>
<script async type="text/javascript" src="%PUBLIC_URL%/libS4.js"></script>

(If using react, you place both libS4.wasm & libS4.js in the public folder. And you can add the above code to public/index.html.)

Note that we setup our ModuleS4 variable BEFORE asking the browser to load the libS4.js file. This ensures our hooks will be in place.

Now in your javascript code you can create an s4 instance like so:

import {S4, S4Module} from 's4js';

// If using Typescript, add these for the compiler:
interface ModuleLoader extends S4Module {
	isRuntimeInitialized: boolean
}
declare var onModuleS4Initialized: Array<()=>void>;
declare var ModuleS4: ModuleLoader;

// And then add this somewhere to initialize S4
const wasmReady = ()=> {

	const s4 = S4.load(ModuleS4);
	if (s4 == null)
	{
		console.log("Failed loading WASM crypto library !");
	}
	else
	{
		console.log("WASM crypto library ready");
		
		// Now go do something cool with crypto...
	}
}

if (ModuleS4.isRuntimeInitialized) {
	wasmReady();
}
else {
	console.log("Waiting for WASM crypto library...");
	onModuleS4Initialized.push(wasmReady);
}

Once you've got your s4 instance, you're ready to use the crypto lib, with blazing fast WebAssembly performance !

Setup - Node.js

Demo - browser

There's example code that demonstrates getting up-and-running in the browser: examples/web/index.html

Due to browser restrictions, you can't simply open the HTML file directly. You'll get the following error:

Fetch API cannot load file:///Users/robbie/Programs/4thA/S4_Javascript/dist.browser/libS4.wasm. URL scheme must be "http" or "https" for CORS request.

So you have to serve the file using a local webserver. The serve tool is one solution:

$ npm install -g serve
$ cd <to s4js ROOT directory>
$ serve
   ┌───────────────────────────────────────────────────┐
   │                                                   │
   │   Serving!                                        │
   │                                                   │
   │   - Local:            http://localhost:5000       │
   │   - On Your Network:  http://192.168.1.212:5000   │
   │                                                   │
   │   Copied local address to clipboard!              │
   │                                                   │
   └───────────────────────────────────────────────────┘

Note that you need to run serve from the project ROOT directory. This is because we need to reference files in /dist.browser.

Finally, run the example in your browser:

http://localhost:5000/examples/web/index.html

Hashing

Several hashing algorithms are supported:

  • MD5
  • SHA1
  • SHA224
  • SHA256
  • SHA384
  • SHA512
  • SKEIN256
  • SKEIN512
  • SKEIN1024
  • SHA512_256
  • xxHash32
  • xxHash64
  • SHA3_224
  • SHA3_256
  • SHA3_384
  • SHA3_512

To hash small amounts of data, the hash_do function is easy:

import {S4HashAlgorithm} from 's4js';

// inputData: Uint8Array
// returns  : Uint8Array
const hashData = s4.hash_do(S4HashAlgorithm.SHA3_256, inputData);

If you want to hash a string, you can convert it to UTF-8:

import {S4HashAlgorithm} from 's4js';
import {TextEncoder} from 'text-encoding-utf-8'

const str = "hash me";
const input = TextEncoder().encode(str);
const hashData = s4.hash_do(S4HashAlgorithm.SHA3_256, inputData);
const hashHexStr = s4.util_hexString(hashData)

To hash large amounts of data (e.g. a file), you'll likely want to do so in chunks:

const hashContext = s4.hash_init(S4HashAlgorithm.SHA3_256);
while (...got another chunk of data of type Uint8Array...)
{
	s4.hash_update(hashContext, data);
}

const hashData = s4.hash_final(hashContext);
s4.hash_free();

Block Ciphers

Todo...

About

A javascript wrapper for the S4 encryption library, using WebAssembly.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published