Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

dozyio/js-blockstore-encrypt

Repository files navigation

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 { CID } from 'multiformats/cid';
(async () => {
 try {
 const password = 'strong-password-is-strong'; // Must be at least 16 bytes long
 const masterSalt = new TextEncoder().encode('4d1A2eF42C9F09BF8ba6141D3dBA3521') // Must be at least 16 bytes long
 const store = new EncBlockstore(new FsBlockstore('./data'));
 await store.init(password, masterSalt);
 await store.open();
 // Use the store as you would use any Blockstore
 const someCid = CID.parse('bafkreigh2akiscaildc6en5ynpwp45fucjk64o4uqa5fmsrzc4i4vqveae')
 const someData = new Uint8Array([1, 2, 3, 4, 5]);
 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.

About

Encrypted Blockstore for IPFS / Helia

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

AltStyle によって変換されたページ (->オリジナル) /