# mongoose-field-encryption
![Build Status](https://github.com/wheresvic/mongoose-field-encryption/workflows/ci-test/badge.svg) [![Coverage Status](https://coveralls.io/repos/github/wheresvic/mongoose-field-encryption/badge.svg?branch=master)](https://coveralls.io/github/wheresvic/mongoose-field-encryption?branch=master)
A zero dependency simple symmetric encryption plugin for individual fields. The goal of this plugin is to encrypt data but still allow searching over fields with string values. This plugin relies on the Node `crypto` module. Encryption and decryption happen transparently during save and find.
While this plugin works on individual fields of any type, note that for non-string fields, the original value is set to undefined after encryption. This is because if the schema has defined a field as an array, it would not be possible to replace it with a string value.
As of the stable 2.3.0 release, this plugin requires provision of a custom salt generation function (which would always provide a constant salt given the secret) in order to retain symmetric decryption capability.
Also consider [mongoose-encryption](https://github.com/joegoldbeck/mongoose-encryption) if you are looking to encrypt the entire document.
## How it works
Encryption is performed using `AES-256-CBC`. To encrypt, the relevant fields are encrypted with the provided secret + random salt (or a custom salt via the provided `saltGenerator` function). The generated salt and the resulting encrypted value is concatenated together using a `:` character and the final string is put in place of the actual value for `string` values. An extra `boolean` field with the prefix `__enc_` is added to the document which indicates if the provided field is encrypted or not.
Fields which are either objects or of a different type are converted to strings using `JSON.stringify` and the value stored in an extra marker field of type `string` with a naming scheme of `__enc_` as prefix and `_d` as suffix on the original field name. The original field is then set to `undefined`. Please note that this might break any custom validation and application of this plugin on non-string fields needs to be done with care.
## Requirements
- Node `>=12` (Use `2.3.4` for Node `>=4.4.7 && <6.x.x`, `5.0.3` for Node `>=6.x.x && <=10.x.x`)
- MongoDB `>=4.4`
- Mongoose `>=4.0.0`
## Installation
`npm install mongoose-field-encryption --save-exact`
## Security Notes
- _Always store your keys and secrets 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. You can also encrypt the password afer hashing it although it is not necessary.
- If an attacker gains access to your application server, they likely have access to both the database and the key. At that point, neither encryption nor authentication do you any good.
## Usage
### Basic
For example, given a schema as follows:
```js
const mongoose = require("mongoose");
const mongooseFieldEncryption = require("mongoose-field-encryption").fieldEncryption;
const Schema = mongoose.Schema;
const PostSchema = new Schema({
title: String,
message: String,
references: {
author: String,
date: Date,
},
});
PostSchema.plugin(mongooseFieldEncryption, {
fields: ["message", "references"],
secret: "some secret key",
saltGenerator: function (secret) {
return "1234567890123456";
// should ideally use the secret to return a string of length 16,
// default = `const defaultSaltGenerator = secret => crypto.randomBytes(16);`,
// see options for more details
},
});
const Post = mongoose.model("Post", PostSchema);
const post = new Post({ title: "some text", message: "hello all" });
post.save(function (err) {
console.log(post.title); // some text (only the message field was set to be encrypted via options)
console.log(post.message); // a9ad74603a91a2e97a803a367ab4e04d:93c64bf4c279d282deeaf738fabebe89
console.log(post.__enc_message); // true
});
```
The resulting documents will have the following format:
```js
{
_id: ObjectId,
title: String,
message: String, // encrypted salt and hex value as string, e.g. 9d6a0ca4ac2c80fc84df0a06de36b548:cee57185fed78c055ed31ca6a8be9bf20d303283200a280d0f4fc8a92902e0c1
__enc_message: true, // boolean marking if the field is encrypted or not
references: undefined, // encrypted object set to undefined
__enc_references: true, // boolean marking if the field is encrypted or not
__enc_references_d: String // encrypted salt and hex object value as string, e.g. 6df2171f25fd1d32adc4a4059f867a82:5909152856cf9cdb7dc32c6af321c8fe69390c359c6b19d967eaa6e7a0a97216
}
```
`find` works transparently and you can make new documents as normal, but you should not use the `lean` option on a find if you want the fields of the document to be decrypted. `findOne`, `findById` and `save` also all work as normal. `update` works _only for string fields_ and you would also need to manually set the `__enc_` field value to false if you're updating an encrypted field.
From the mongoose package documentation: _Note that findAndUpdate/Remove do not execute any hooks or validation before making the change in the database. If you need hooks and validation, first query for the document and then save it._
Note that as of `1.2.0` release, support for `findOneAndUpdate` has also been added. Note that you would need to specifically set the encryption field marker for it to be encrypted. For example:
```js
Post.findOneAndUpdate({ _id: postId }, { $set: { message: "snoop", __enc_message: false } });
```
The above also works for non-string fields. See changelog for more details.
Also note that if you manually set the value `__enc_` prefix field to true then the encryption is not run on the corresponding field and this may result in the plain value being stored in the db.
### Search over encrypted fields
Note that in order to use this option a _fixed_ salt generator must be provided. See example as follows:
```js
const messageSchema = new Schema({
title: String,
message: String,
name: String,
});
messageSchema.plugin(mongooseFieldEncryption, {
fields: ["message", "name"],
secret: "some secret key",
saltGenerator: function (secret) {
return "1234567890123456";
// should ideally use the secret to return a string of length 16,
// default = `const defaultSaltGenerator = secret => crypto.randomBytes(16);`,
// see options for more details
},
});
const title = "some text";
const name = "victor";
const message = "hello all";
const Message = mongoose.model("Message", messageSchema);
const messageToSave = new Message({ title, message, name });
await messageToSave.save();
// note that we are only providing the field we would like to search with
const messageToSearchWith = new Message({ name });
messageToSearchWith.encryptFieldsSync();
// `messageToSearchWith.name` contains the encrypted string text
const results = await Message.find({ name: messageToSearchWith.name });
// results is an array of length 1 (assuming that there is only 1 message with the name "victor" in the collection)
// and the message in the results array corresponds to the one saved previously
```
### Options
- `fields` (required): an array list of the required fields
- `secret` (required): a string cipher (or a synchronous factory function which returns a string cipher) which is used to encrypt the data (don't lose this!)
- `useAes256Ctr` (optional, default `false`): a boolean indicating whether the older `aes-256-ctr` algorithm should be used. Note that this is strictly a backwards compatibility feature and for new installations it is recommended to leave this at default.
- `saltGenerator` (optional, default
没有合适的资源?快使用搜索试试~ 我知道了~
用于单个字段的简单对称加密插件。无依赖性,只有mongoose对等依赖性。.zip
共23个文件
js:8个
md:4个
json:3个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 103 浏览量
2023-03-23
21:30:41
上传
评论
收藏 101KB ZIP 举报
温馨提示
用于单个字段的简单对称加密插件。无依赖性,只有mongoose对等依赖性。
资源推荐
资源详情
资源评论
收起资源包目录
用于单个字段的简单对称加密插件。无依赖性,只有mongoose对等依赖性。.zip (23个子文件)
mongoose-field-encryption-master
SECURITY.md 322B
lib
mongoose-field-encryption.d.ts 404B
mongoose-field-encryption.js 8KB
.prettierrc 107B
.github
workflows
ci.yml 804B
codeql-analysis.yml 2KB
LICENSE 1KB
CONTRIBUTING.md 473B
CHANGELOG.md 38B
package.json 2KB
development
docker-compose-dev.yml 571B
init-mongo-dev.js 144B
package-lock.json 315KB
.npmignore 0B
test
setup.js 301B
test-basic-usage.js 3KB
test-manual-encryption.js 812B
test-db.js 22KB
test-setup.js 1KB
test-statics.js 21KB
.gitignore 428B
tsconfig.json 186B
README.md 16KB
共 23 条
- 1
资源评论
快撑死的鱼
- 粉丝: 1w+
- 资源: 9154
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功