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

firecrypt

v3.1.1

Published

Transparent encryption for Firebase

Downloads

153

Readme

firecrypt — transparent at-rest AES encryption for Firebase

Project Status: Active - The project has reached a stable, usable state and is being actively developed.

First: this library only makes sense if your clients sit behind a firewall, or if you control who can get an account and anonymous users don't need to access encrypted data. Otherwise, the encryption key will be public defeating the whole point.

This library monkey-patches either the Firebase Admin SDK or the Firebase JavaScript Client SDK to automatically encrypt and decrypt keys and values of your choosing using AES-SIV. Almost everything just works, except that startAt and endAt queries on encrypted data would produce randomly ordered results and so are forbidden. equalTo queries will work fine, however, since a given plaintext value will always encrypt to the same ciphertext — but it will also let an attacker know if any two values are equal, even if they don't know what they are.

The library works both in Node (4.x+) and in the browser. In the browser, you need to also load crypto-js (the following modules are sufficient: core.js, enc-base64.js, md5.js, evpkdf.js, cipher-core.js, aes.js, mode-ctr.js) and cryptojs-extension (only build/siv.js is required). If you want to enable caching to enhance performance, then in the browser you'll also want to load node-lru-cache. All these libraries are automatically included in the Node distribution.

Upon requiring this library, the admin.database() or firebase.database() method as well as the app.App.database() methods are monkey-patched to return a custom FireCrypt instance in place of standard admin.database.Database or firebase.database.Database instances. The FireCrypt instance generally has the same API, although you must first configure the encryption before it can be used:

Configure FireCrypt With Firebase Admin SDK:

const admin = require('firebase-admin');
const FireCrypt = require('firecrypt');

const app = admin.initializeApp({
  // ...
})

const db = admin.database();  // OR const db = app.database();

const encryptionKeyCheckValue = db.configureEncryption(options, specification);

Configure FireCrypt With Firebase Client SDK:

const firebase = require('firebase');
const FireCrypt = require('firecrypt');

const app = firebase.initializeApp({
  // ...
})

const db = firebase.database();  // OR const db = app.database();

const encryptionKeyCheckValue = db.configureEncryption(options, specification);

The options are as follows:

  • algorithm: the crypto algorithm to use. Currently supported values are:
    • aes-siv: actual encryption using AES-SIV.
    • passthrough: fake encryption using an identity transform, useful for debugging.
    • none: no encryption, will throw an error with firecrypt === 'NO_KEY' if you attempt to read or write any encrypted path.
  • key: the required key for algorithm aes-siv. Must be 32, 48, or 64 bytes, encoded in base 64. You can generate such a key using openssl rand -base64 64. If you attempt to decrypt a value with the wrong key then an error with firecrypt === 'WRONG_KEY' will be thrown.
  • encryptionKeyCheckValue: a value generated by a previous call to configureEncryption() used to verify that the aes-siv key used in both calls is the same. If a different key was used to generate the encryptionKeyCheckValue then an error with firecrypt === 'WRONG_KEY' will be thrown.
    • For convenience, the encryptionKeyCheckValue is also available at any time via admin.database().encryptionKeyCheckValue or firebase.database().encryptionKeyCheckValue.
  • cacheSize: the maximum size in bytes of the encryption and decryption caches, used to improve performance. In the browser, the caches will only be activated if LRUCache is defined; it should conform to the API of node-lru-cache. You can also specify encryptionCacheSize and decryptionCacheSize separately.

If the algorithm is aes-siv then configureEncryption() will return a value that can be used to synchronously verify whether another key matches by passing it via encryptionKeyCheckValue. This can be useful if the key is distributed as part of a session, and you want to check if you need to invalidate the session because the key has been rotated. Also, if the key doesn't match then decrypting will throw an exception later.

The specification is a JSON structure similar to Firebase security rules but specifying which keys and values need to be encrypted instead. The structure mimics that of your datastore and uses $wildcards in the same manner as security rules.

{
  "rules": {
    "foo": {
      ".encrypt": {"value": "#"}
    },
    "bar": {
      "$baz": {
        ".encrypt": {"key": "#-#-."}
      }
    }
  }
}

Each .encrypt directive can require the key or value (or both) at that path to be encrypted. The parameter is an encryption pattern, where # are placeholders for chunks to be encrypted, . for chunks that should not be encrypted, and everything else is matched verbatim to the plaintext data. Normally, you'll just use a single # to encrypt the entire key or value, but sometimes it can be useful to encrypt only specific parts of a composite key. You can also specify an empty pattern to explicitly indicate that something should not be encrypted, which is only useful if you're encrypting a sibling wildcard key but don't want some specific instances to be encrypted.

You must specify value encryption at the atomic data leaves only — it's not valid to encrypt an object and trying to do so will throw an exception at runtime. There's currently no way to require encryption for an entire subtree.

For bulk encryption/decryption (including key rotation), you can also specify ".encrypt": {"few": true} on wildcard keys (whether encrypted or not) where the number of children is expected to be low enough that it's reasonable to read or write them all at once.

You may want to check out fireplan for a convenient way to generate the encryption specification from your security rules schema. See also firecrypt-tools for related utilities.

Local Setup

Run the following commands from the command line to get your local environment set up:

$ git clone [email protected]:Reviewable/firecrypt.git
$ cd firecrypt    # go to the firecrypt directory
$ npm install     # install local npm dependencies

Run the following command to build the distribution files for the library:

$ npm run build

This will generate the following distribution files, along with accompanying source maps:

  • dist/node/firecrypt.js - A non-minified CommonJS build of the library for use in Node.js.
  • dist/browser/firecrypt.js - A non-minified IIFE build of the library for use in the browser.
  • dist/browser/firecrypt.min.js - A minified IIFE build of the library for use in the browser.