# encryptedfs

> Virtualised persistent encrypted filesystem

Latest version **4.0.4** (published 2025-05-01) · Apache-2.0 license · 98 weekly downloads

## Install

```sh
npm install encryptedfs
pnpm add encryptedfs
yarn add encryptedfs
bun add encryptedfs
```

## Health

**Score 30/100 (F)** — status: maintenance-mode.

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types.

Negative: stale; low maintenance score.

## Facts

| | |
|---|---|
| Version | 4.0.4 |
| Published | 2025-05-01 |
| First published | 2019-03-06 |
| Weekly downloads | 98 |
| License | Apache-2.0 |
| TypeScript types | none |
| Module format | ESM |
| Dependencies | 13 |
| Unpacked size | 436.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 11 |
| Author | Matrix AI |
| Maintainers | brianbotha74, cmcdragonkai, matrixai-bot, aashwin |
| Keywords | filesystem, encryption |

## Links

- npm: https://www.npmjs.com/package/encryptedfs
- Repository: https://github.com/MatrixAI/js-encryptedfs
- Homepage: https://github.com/MatrixAI/js-encryptedfs#readme
- Issues: https://github.com/MatrixAI/js-encryptedfs/issues
- npm.io page: https://npm.io/package/encryptedfs

## Dependencies (13)

- [errno](https://npm.io/package/errno.md) ^0.1.7
- [node-forge](https://npm.io/package/node-forge.md) ^1.3.1
- [@matrixai/db](https://npm.io/package/@matrixai/db.md) ^6.0.22
- [readable-stream](https://npm.io/package/readable-stream.md) ^3.6.0
- [@matrixai/errors](https://npm.io/package/@matrixai/errors.md) ^2.1.3
- [@matrixai/logger](https://npm.io/package/@matrixai/logger.md) ^4.0.3
- [resource-counter](https://npm.io/package/resource-counter.md) ^1.2.4
- [util-callbackify](https://npm.io/package/util-callbackify.md) ^1.0.0
- [@matrixai/workers](https://npm.io/package/@matrixai/workers.md) ^2.0.1
- [@matrixai/resources](https://npm.io/package/@matrixai/resources.md) ^2.0.1
- [@matrixai/async-init](https://npm.io/package/@matrixai/async-init.md) ^2.1.2
- [@matrixai/async-locks](https://npm.io/package/@matrixai/async-locks.md) ^5.0.2
- [lexicographic-integer](https://npm.io/package/lexicographic-integer.md) ^1.1.0

## Alternatives

- [unionfs](https://npm.io/package/unionfs.md) — 2.2M weekly downloads
- [path-starts-with](https://npm.io/package/path-starts-with.md) — 35.9K weekly downloads
- [redzip](https://npm.io/package/redzip.md) — 1.2K weekly downloads
- [vscode-anymatch](https://npm.io/package/vscode-anymatch.md) — 848 weekly downloads
- [@ledgerhq/coin-filecoin](https://npm.io/package/@ledgerhq/coin-filecoin.md) — 793 weekly downloads

## Recent versions

- 4.0.4 (latest) — 2025-05-01
- 4.0.3 — 2025-05-01
- 4.0.2 — 2025-03-31
- 4.0.1 — 2025-03-27
- 3.5.9 — 2025-02-04
- 3.5.8 — 2023-06-28
- 3.5.6 — 2022-08-22
- 3.5.5 — 2022-07-28
- 3.5.3 — 2022-06-01
- 3.5.2 — 2022-05-31
- 3.5.1 — 2022-05-12
- 3.5.0 — 2022-05-09
- 3.4.3 — 2022-01-27
- 3.4.2 — 2022-01-23
- 3.4.1 — 2022-01-21
- … 21 more at https://npm.io/package/encryptedfs/versions

## README

# js-encryptedfs

Encrypted filesystem library for TypeScript/JavaScript applications

* Virtualised - files, directories, permissions are all virtual constructs, they do not correspond to real filesystems
* Orthogonally Persistent - all writes automatically persisted
* Encrypted-At-Rest - all persistence is encrypted
* Random Read & Write - encryption and decryption operates over fixed-block sizes
* Streamable - files do not need to loaded fully in-memory
* Comprehensive continuous benchmarks in CI/CD

Development based on js-virtualfs: https://github.com/MatrixAI/js-virtualfs

## Installation

```sh
npm install --save encryptedfs
```

## Usage

```ts
import type { EFSWorkerModule } from 'encryptedfs';

import { WorkerManager } from '@matrixai/workers';
import { EncryptedFS, utils } from 'encryptedfs';

const key = utils.generateKeySync(256);

const efs = await EncryptedFS.createEncryptedFS({
  dbPath: '/tmp/efs',
  dbKey: key,
});

// optionally set up the worker manager for multi-threaded encryption/decryption
const workerManager = await WorkerManager.createWorkerManager<EFSWorkerModule>({
  workerFactory: () => spawn(new Worker('./src/workers/efsWorker'))
});

efs.setWorkerManager(workerManager);

// create a new directory
const newDir = `test`;
await efs.mkdir(newDir);

// write out to a file
await efs.writeFile(`${newDir}/testFile`, 'output');

// read in the file (contents = 'output')
const contents = await efs.readFile(`${newDir}/testFile`);

// closes the EFS
await efs.stop();

// destroys the EFS state
await efs.destroy();
```

### Encryption & Decryption Protocol

Encryption & Decryption implemented using the `node-forge` library. However it is possible to plug in your own `encrypt` and `decrypt` functions.

Internally we use the AES-GCM symmetric encryption using a master `dbKey` that can be 128, 192 or 256 bits long.

The `dbKey` can be generated from several methods:

* `generateKey` - random asynchronous
* `generateKeySync` - random synchronous
* `generateKeyFromPass` - derived from user-provided "password" asynchronous
* `generateKeyFromPassSync` - derived from user-provided "password" synchronous

For example:

```ts
const [key, salt] = await generateKeyFromPass('secure password');
```

This uses PBKDF2 to derive a symmetric key. The default key length will be 256 bits. For deterministic key generation, make sure to specify the `salt` parameter.

```ts
const [key, salt] = await generateKeyFromPass('secure password', 'salt');
```

Construction of `EncryptedFS` relies on an optional `blockSize` parameter. This is by default set to 4 KiB. All files are broken up into 4 KiB plaintext blocks. When encrypted, they are persisted as ciphertext blocks.

The ciphertext blocks contain an initialization vector plus an authorisation tag. Here is an example of the structure:

```
| iv (16 bytes) | authTag (16 bytes) | ciphertext data (x bytes) |
```

The ciphertext data length is equal to the plaintext block length.

### Differences with Node Filesystem

There are some differences between EFS and Node FS:

* User, Group and Other permissions: In EFS User, Group and Other permissions are strictly confined to their permission class. For example, a User in EFS does not have the permissions that a Group or Other has while in Node FS a User also has permissions that Group and Other have.
* Sticky Files: In Node FS, a sticky bit is a permission bit that is set on a file or a directory that lets only the owner of the file/directory or the root user to delete or rename the file. EFS does not support the use of sticky bits.
* Character Devices: Node FS contains Character Devices which can be written to and read from. However, in EFS Character Devices are not supported yet.

## Development

Run `nix develop`, and once you're inside, you can use:

```sh
# install (or reinstall packages from package.json)
npm install
# build the dist
npm run build
# run the repl (this allows you to import from ./src)
npm run tsx
# run the tests
npm run test
# lint the source code
npm run lint
# automatically fix the source
npm run lintfix
```

## Benchmarks

```sh
npm run bench
```

View benchmarks here: https://github.com/MatrixAI/js-encryptedfs/blob/master/benches/results with https://raw.githack.com/

### Docs Generation

```sh
npm run docs
```

See the docs at: https://matrixai.github.io/js-encryptedfs/

### Publishing

Publishing is handled automatically by the staging pipeline.

Prerelease:

```sh
# npm login
npm version prepatch --preid alpha # premajor/preminor/prepatch
git push --follow-tags
```

Release:

```sh
# npm login
npm version patch # major/minor/patch
git push --follow-tags
```

Manually:

```sh
# npm login
npm version patch # major/minor/patch
npm run build
npm publish --access public
git push
git push --tags
```

---
_Source: https://npm.io/package/encryptedfs · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
