Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

mongoose-encryption

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mongoose-encryption

Simple encryption plugin for Mongoose

  • 0.11.1
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
5.4K
increased by10.06%
Maintainers
1
Weekly downloads
 
Created
Source

mongoose-encryption

Simple encryption for mongoose documents. Relies on the Node crypto module. Encryption and decryption happen transparently during save and find. Rather than encrypting fields individually, this plugin takes advantage of the BSON nature of mongoDB documents to encrypt multiple fields at once.

How it Works

Encryption is performed using aes-256-cbc with a random, unique initialization vector for each operation.

To encrypt, the relevant fields are removed from the document, converted to JSON, enciphered in Buffer format with the IV prepended, and inserted into the _ct field of the document. Mongoose converts the _ct field to Binary when sending to mongo.

To decrypt, the _ct field is deciphered, the JSON is parsed, and the individual fields are inserted back into the document as their original data types.

Installation

npm install mongoose-encryption

Usage

Generate and store encryption key separately. It should be a 32-byte base64 string. It should probably live in an environment variable, but be sure not to lose it. A great way to securely generate such a key is openssl rand -base64 32

Basic

By default, all fields are encrypted except for _id, __v, and fields with indexes

var mongoose = require('mongoose');
var encrypt = require('mongoose-encryption');

var userSchema = new mongoose.Schema({
	name: String,
	age: Number
	// whatever else
});

// Add any other plugins or middleware here. For example, middleware for hashing passwords

var encryptionKey = process.env.SOME_32BYTE_BASE64_STRING;

userSchema.plugin(encrypt, { key: encryptionKey });
// This adds a _ct field to the schema, as well as pre 'init' and pre 'save' middleware,
// and encrypt and decrypt instance methods

User = mongoose.model('User', userSchema);

And you're all set. You should be able to find and make New documents as normal, but you should not use the lean option on a find if you want the document to be decrypted. findOne, findById, etc..., as well as save and create also all work as normal. update will work fine on unencrypted fields, but will not work correctly if encrypted fields are involved.

Exclude Certain Fields from Encryption

To exclude additional fields (other than _id and indexed fields), pass the exclude option

// exclude age from encryption, still encrypt name. _id will also remain unencrypted
userSchema.plugin(encrypt, { key: encryptionKey, exclude: ['age'] });

Encrypt Only Certain Fields

You can also specify exactly which fields to encrypt with the fields option. This overrides the defaults and all other options.

// encrypt age regardless of any other options. name and _id will be left unencrypted
userSchema.plugin(encrypt, { key: encryptionKey, fields: ['age'] });

Encrypt Specific Fields of Sub Docs

You can even encrypt fields of sub-documents, you just need to add the encrypt plugin to the subdocument schema. You should also add the encrypt.encryptedChildren plugin to the parent if you continue to work with documents following failed saves caused by validation errors.

var hidingPlaceSchema = new Schema({
  latitude: Number,
  longitude: Number,
  nickname: String
});

hidingPlaceSchema.plugin(encrypt, {
  key: process.env.KEY,
  exclude: ['nickname']
});

var userSchema = new Schema({
  name: String,
  locationsOfGold: [hidingPlaceSchema]
});

userSchema.plugin encrypt.encryptedChildren // only needed for correct document behavior following validation errors during a save

The need for encrypt.encryptedChildren arises because subdocument 'pre save' hooks are called before parent validation completes, and there are no subdocument hooks that fire when parent validation fails. Without the plugin, if you repair a parent doc after a failed save and then try to save again, data in the encrypted fields of the subdocuments will be lost.

Instance Methods

You can also encrypt and decrypt documents at will (as long as the model includes the plugin). decrypt is idempotent. encrypt is not.

joe = new User ({ name: 'Joe', age: 42 });
joe.encrypt(function(err){
	if (err) return handleError(err);
	console.log(joe.name); // undefined
	console.log(joe.age); // undefined
	console.log(joe._ct); // <Buffer 4a 89 9e df 60 ...

	joe.decrypt(function(err){
		if (err) return handleError(err);
		console.log(joe.name); // Joe
		console.log(joe.age); // 42
		console.log(joe._ct); // undefined
	});
});

There is also a decryptSync function, which executes synchronously and throws if an error is hit.

Pros & Cons of Encrypting Multiple Fields at Once

Advantages:

  • All Mongoose data types supported via a single code path
  • Faster encryption/decryption when working with the entire document
  • Smaller encrypted documents

Disadvantages:

  • Cannot select individual encrypted fields in a query nor unset or rename encrypted fields via an update operation
  • Potentially slower in cases where you only want to decrypt a subset of the document

Security Notes

  • Always store your encryption key outside of version control and separate from your database. An environment variable on your application server works well for this.
  • Additionally, store your encryption key offline somewhere safe. If you lose it, there is no way to retrieve your encrypted data.
  • Encrypting passwords is no substitute for appropriately hashing them. bcrypt is one great option. Here's one nice implementation. Once you've already hashed the password, you may as well encrypt it too. Defense in depth, as they say. Just add the mongoose-encryption plugin to the schema after any hashing middleware.
  • If an attacker gains access to your application server, they likely have access to both the database and the key. At that point, encryption does you no good.

How to Run Unit Tests

  1. Install dependencies with npm install and install mongo if you don't have it yet
  2. Start mongo with mongod
  3. Run tests with npm test

Security Issue Reporting / Disclaimer

None of the authors are security experts. We relied on accepted tools and practices, and tried hard to make this tool solid and well-tested, but pobody's nerfect. Please look over the code carefully before using it (and note the legal disclaimer below). If you find or suspect any security-related issues, please email us at security@cinchfinancial.com and we will get right on it. For non-security-related issues, please open a Github issue or pull request.

License

The MIT License (MIT)

Copyright (c) 2014 Joseph Goldbeck and Connect Financial, LLC

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Keywords

FAQs

Package last updated on 15 Dec 2015

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc