The Future of File Utilities: encryption, hashing and compression in the browser

I was wondering if the time has come where browser tech is secure and powerful enough to replace some of the niche command line tools that we are used to in Linux. Normally I’d have to download some variant of them on each operating system or device I’m working on. This can get annoying. Some of the most common niche tools are encryption, hashing and compression of files.

Turns out that the browser is more than capable to deliver this funcitonality thanks to some awesome open source projects. Imagine in the future having a plethora of file tools implemented in the browser: file editor, diff, hex dump, hex edit, all kinds of compression, encryption, hashing, search and replace of text and so on. We can potentially pipe the output of these tools to third party APIs to save the files on cloud storage or process them further. This can open a new era for file tools. And the best part is its all cross-platform. The tools can run uniformly on any operating system and any device that supports a major browser.

File Utilities

After my experience with building SecureMyFiles, a client-side encryption product for desktop operating systems, I got curious if we can achieve similar functionality directly in the browser. My main requirement was that all file operations must be performed on the client side with no data being transferred to a server. The idea is to use the bowser as a cross-platform execution engine to run the file utilities on any operating system, including mobile devices. This way we can avoid downloading specialized tools as we move from device to device.

I’ve open sourced the tools on GitHub: https://github.com/stanimirivanovde/browser-power

File Encryption in the Browser

I was able to create an efficient file encryption and decryption utility in the browser that runs completely on the client side. Both encryption and decryption are efficient and run in constant memory achieving 9MB/s. They don’t match the performance of their command-line alternatives but given the fact that they can run on most devices that can run a browser I think it is a good start.

The Javascript library I decieded to use is forge. The need to run with constant memory regardless of the file size requires a cipher that can be updated in chunks. The forge implementation worked quite well. Unfortunately the native Web Crypto API does not support chunked based encryption which was disappointing.

The encryption algorithm I use is AES-GCM with 12 byte IV and 128 bit tag. The key is derived from a password and a randomly generated 128 bit salt passed through PBKDF2 with 100K iterations. The IV is initialized to all 0s (deterministic construction). It is never re-used and each encryption generates a new key. The structure of the encrypted file is:

| 128 bit salt | encrypted file contents | 128 bit tag |

File Encryptor on GitHub: https://stanimirivanovde.github.io/browser-power/encrypt-file.html

File Decryptor on GitHub: https://stanimirivanovde.github.io/browser-power/decrypt-file.html

File Hashing in the Browser

The file hasher produces SHA-256 hash. It also uses the forge crypto library. It operates on 1MB chunks and can read files with arbitrary size using constant memory. The speed is around 6 times slower than the command line utility sha256sum on my MacBook Pro. But nevertheless it works great in the browser.

File Hasher on GitHub: https://stanimirivanovde.github.io/browser-power/hash-file.html

File Compression

I decided to use the pako compression library. It achieves good speed and uses the zlib compression algorithm. I tested compressing a 34GB file (VirtualBox vdi file). It took some time but finished successfully on my MacBook Pro with 16GB of RAM. The file format is not pure gzip which is unfortunate since other tools cannot be used to decompress the file.

File Compressor on GitHub: https://stanimirivanovde.github.io/browser-power/compress-file.html

File Decompressor on GitHub: https://stanimirivanovde.github.io/browser-power/decompress-file.html

What’s next

Why not compress and encrypt at the same time? Why not compress, encrypt and push to Dropbox using their API? This way I have my file ready to be shared with whoever I want. What other use cases can you think of?