npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

blockstore-enc

v1.0.1

Published

A JS/TS transparent encrypted wrapper around any existing Blockstore implementation.

Downloads

5

Readme

blockstore-enc

A JS/TS transparent encrypted wrapper around any existing Blockstore implementation.

Features

  • Data Security: Encrypts blocks to ensure privacy and security. CIDs are stored as secure hashes.
  • Compatibility: Works with any Blockstore implementation conforming to the interface-blockstore specification.
  • Strong Cryptography:
    • Uses AES-GCM for block encryption.
    • Uses HMAC-SHA256 for CID hashing.
    • Master key is derived from a password using PBKDF2.
    • Derives encryption and MAC keys from a master key using HKDF.

Installation

npm install blockstore-enc

Or with Yarn:

yarn add blockstore-enc

Usage

import { EncBlockstore } from 'blockstore-enc';
import { FsBlockstore } from 'blockstore-fs';
import fs from 'fs';

(async () => {
  try {
    const password = 'strong-password-is-strong'; // Must be at least 16 bytes long

    // Generate or retrieve the master salt (must be at least 16 bytes)
    // If initializing for the first time, generate and store this salt securely.
    // If reopening an existing store, retrieve the salt from storage.
    let masterSalt;

    const saltFile = 'path/to/saltfile';

    if (fs.existsSync(saltFile)) {
      masterSalt = fs.readFileSync(saltFile);
    } else {
      masterSalt = crypto.getRandomValues(new Uint8Array(16));
      fs.writeFileSync(saltFile, Buffer.from(masterSalt));
    }

    const store = new EncBlockstore(new FsBlockstore('path/to/store'));
    await store.init(password, masterSalt);
    await store.open();

    // Use the store as you would use any Blockstore
    const someCid = /* your CID */;
    const someData = /* your data as Uint8Array */;
    await store.put(someCid, someData);

    const data = await store.get(someCid);
    console.log('Retrieved data:', data);
  } catch (err) {
    console.error(err);
  }
})();

API

Class: EncBlockstore

Constructor

new EncBlockstore(blockstore: Blockstore, init?: EncBlockstoreInit)

Creates a new instance of EncBlockstore wrapping the provided blockstore.

  • blockstore: The underlying Blockstore to wrap.
  • init (optional): Initialization options.

Methods

init(password: string, masterSalt: Uint8Array): Promise<void>

Initializes the encryption and MAC keys. Must be called before using the blockstore.

  • password: The password to derive the master key from. Must be at least 16 bytes long.
  • masterSalt: The master salt used for key derivation. Must be at least 16 bytes long.
open(): Promise<void>

Opens the underlying blockstore.

close(): Promise<void>

Closes the underlying blockstore.

put(key: CID, val: Uint8Array): Promise<CID>

Encrypts and stores a block under the original CID.

  • key: The original CID.
  • val: The plaintext data to encrypt and store.
  • Returns: The original CID.
get(key: CID): Promise<Uint8Array>

Retrieves and decrypts a block by its original CID.

  • key: The original CID.
  • Returns: The decrypted plaintext data.

Deletes a block by its original CID.

  • key: The original CID.
has(key: CID): Promise<boolean>

Checks if a block exists by its original CID.

  • key: The original CID.
  • Returns: A boolean indicating existence.
putMany(source: AwaitIterable<Pair>): AsyncIterable<CID>

Stores multiple blocks in parallel.

  • source: An iterable of { cid, block } pairs.
  • Returns: An async iterable of CIDs.
getMany(source: AwaitIterable<CID>): AsyncIterable<Pair>

Retrieves multiple blocks in parallel.

  • source: An iterable of CIDs.
  • Returns: An async iterable of { cid, block } pairs.
deleteMany(source: AwaitIterable<CID>): AsyncIterable<CID>

Deletes multiple blocks in parallel.

  • source: An iterable of CIDs.
  • Returns: An async iterable of deleted CIDs.

Initialization Options (EncBlockstoreInit)

You can configure the behavior of the EncBlockstore using the init parameter.

  • pbkdf2Iterations (number): The number of PBKDF2 iterations to use. Default: 210000 for SHA-512.
  • pbkdf2hash ('SHA-512' | 'SHA-256'): The hash algorithm to use for PBKDF2. Default: 'SHA-512'.
  • saltByteLength (number): The length of the salt to use for PBKDF2. Default: 16 bytes.
  • putManyConcurrency (number): How many blocks to put in parallel when .putMany is called. Default: 50.
  • getManyConcurrency (number): How many blocks to read in parallel when .getMany is called. Default: 50.
  • deleteManyConcurrency (number): How many blocks to delete in parallel when .deleteMany is called. Default: 50.

Cryptography Details

  • Key Derivation:
    • Uses PBKDF2 to derive a master key from the password and master salt.
    • Default PBKDF2 settings: 210,000 iterations and SHA-512 hash function.
  • Key Expansion:
    • Uses HKDF with SHA-256 to derive separate encryption and MAC keys from the master key.
    • The encryption key is used for per-block key derivation.
  • Per-block Encryption:
    • For each block, a unique per-block salt is generated.
    • Uses HKDF with the per-block salt to derive a per-block encryption key.
    • The block data is encrypted using AES-GCM with a random IV.
    • The salt and IV are stored alongside the encrypted data.
  • CID Hashing:
    • The original CID is transformed using HMAC-SHA256 with the MAC key to compute a storage CID.
    • The storage CID serves as a mapping to the original CID - it is not a content addressed hash of the encrypted block.
    • The storage CID is used to store and retrieve the encrypted block.

Security Considerations

  • Password and Salt:
    • The security of the encrypted blockstore depends critically on the secrecy of the password and the master salt.
    • If either is compromised, the encrypted data may be at risk.
    • If either is lost, the data cannot be recovered.

Limitations

  • No getAll Support:

    • Due to the one-way mapping of CIDs, the getAll() method is not supported.
  • Performance Overhead:

    • Encryption and decryption operations introduce computational overhead.