{"_id":"@cpwc/mongoose-field-encryption","_rev":"6-766a673ffbda45c89a35968cb0abd982","time":{"3.0.8":"2020-09-17T16:50:26.085Z","created":"2020-09-17T16:50:48.087Z","3.0.9":"2020-09-17T16:50:48.240Z","modified":"2022-04-05T01:33:38.051Z"},"name":"@cpwc/mongoose-field-encryption","dist-tags":{"latest":"3.0.9"},"versions":{"3.0.9":{"name":"@cpwc/mongoose-field-encryption","version":"3.0.9","description":"A simple symmetric encryption plugin for individual fields.","main":"lib/mongoose-field-encryption.js","scripts":{"test":"mocha","test:auth":"URI='mongodb://mfe:mfe@127.0.0.1:27017/mongoose-field-encryption-test' npm test","test-coverage":"nyc --reporter=html --reporter=text ./node_modules/mocha/bin/_mocha && chromium-browser ./coverage/index.html","test-coverage:auth":"URI='mongodb://mfe:mfe@127.0.0.1:27017/mongoose-field-encryption-test' nyc --reporter=html --reporter=text ./node_modules/mocha/bin/_mocha && chromium-browser ./coverage/index.html","release-it":"release-it"},"repository":{"type":"git","url":"git+https://github.com/wheresvic/mongoose-field-encryption.git"},"keywords":["mongoose","encryption","field","cqrs","string","encrypt","security","search","searchable","mongo"],"author":{"name":"Victor Parmar","email":"victorparmar@gmail.com","url":"https://smalldata.tech"},"contributors":[],"license":"MIT","bugs":{"url":"https://github.com/victorparmar/mongoose-field-encryption/issues"},"peerDependencies":{"mongoose":">=5.4.0"},"devDependencies":{"bluebird":"3.7.2","chai":"4.2.0","coveralls":"3.1.0","mocha":"6.2.2","mongoose":"5.9.21","nyc":"15.1.0","release-it":"13.6.4","sinon":"9.0.2"},"release-it":{"hooks":{"before:init":"npm run test:auth","before:bump":null,"after:bump":null,"before:release":null,"after:release":"git describe --abbrev=0 --tags"},"npm":{"publish":true},"github":{"release":true},"gitlab":{"release":false}},"gitHead":"568eb9d69b7b8d54da135f1eeeb565c190412c7e","homepage":"https://github.com/wheresvic/mongoose-field-encryption#readme","_id":"@cpwc/mongoose-field-encryption@3.0.9","_nodeVersion":"12.18.3","_npmVersion":"6.14.6","dist":{"integrity":"sha512-UUp5ePypC0NlYUB34e1/Td0BSP3Ep4q9worMCnw3lHlsCtPLgiDws3Xq8YWmqUYLfbYkgzYYewypzh/rOUOsIw==","shasum":"f44113eb42f64926518669506c071566fb77ed61","tarball":"https://registry.npmjs.org/@cpwc/mongoose-field-encryption/-/mongoose-field-encryption-3.0.9.tgz","fileCount":5,"unpackedSize":23534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfY5PoCRA9TVsSAnZWagAAf7oP/jHBB+iBoAb107HcXWE8\n+mGZ6mm3hjeXFLS3rT14qqbozKF4R4iAUV5Vwq0TDFykkY6mfm2eU7+tsarT\n7tMCZnev+fk1LL0VW40JCEzAlS+9cy4Ckq93ieqGx/IcVQnli+TAQeQcieRn\nPTqHWXo/ywy9cYHG6jaxTsOZPFzRrINsXMX5SxjpGSq+SJg09khMPd9KQazq\nVNUu5CRPnYGs+SGTtSCkEQaUt8lUjz+TbHjFlkOsSaYdkDB3ClNIZItZ/RRN\nRpc7b2AyxHsj2+7SGWcSfvk0J4k+7CZLcTRHbbQli+XH1yhJHIS8dGHiV9q5\nWI4PC/zNouv0EIo4sRZUkBPJcfA75QtD7LpV/hLufDVlSMV6UNZumP4TzDTa\nXhL6cwBROBCb/9+OlcNd3O6dbSsdBQZ+qEfy3u47S7WYX1bAJwKl8WauDSPu\nIQLwynOoUokZKr/UqJTwCLbTohXxsr0bbwt4gx838vQpsqked4qcwB+kgasI\n5OVsp3byoP4sabS/aWLk843gd+NM1BjAgnqeN/Sfo5Jy3SS2fAsC3oJYIc/U\noH3HCRj7jwTylizb80f9kklVAgL+7MheD4FN5UAapctvP+G0tXjUya9C1cib\nvNvjXryOBaOD3yKQr17adiwrW2Cms/BzYRqJKko3+2gGzNPa7VUv3HCb6C1C\nDGJw\r\n=v+kX\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKVZTq26f08GT0p20t2OKIlm2HeAy+bTd+hBlTFktfgQIhAL/IlUzSDWrC4lXOd2SkVX2BMvx++FxDGm8yNcEj2AOH"}]},"maintainers":[{"name":"cpwc","email":"calvinpohwc@gmail.com"}],"_npmUser":{"name":"cpwc","email":"calvinpohwc@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/mongoose-field-encryption_3.0.9_1600361448120_0.9919387712887069"},"_hasShrinkwrap":false}},"maintainers":[{"name":"cpwc","email":"calvinpohwc@gmail.com"}],"description":"A simple symmetric encryption plugin for individual fields.","homepage":"https://github.com/wheresvic/mongoose-field-encryption#readme","keywords":["mongoose","encryption","field","cqrs","string","encrypt","security","search","searchable","mongo"],"repository":{"type":"git","url":"git+https://github.com/wheresvic/mongoose-field-encryption.git"},"contributors":[],"author":{"name":"Victor Parmar","email":"victorparmar@gmail.com","url":"https://smalldata.tech"},"bugs":{"url":"https://github.com/victorparmar/mongoose-field-encryption/issues"},"license":"MIT","readme":"# mongoose-field-encryption\n\n[![Build Status](https://travis-ci.org/wheresvic/mongoose-field-encryption.svg?branch=master)](https://travis-ci.org/wheresvic/mongoose-field-encryption) [![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)\n\nA 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.\n\nWhile 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.\n\nAs 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.\n\nAlso consider [mongoose-encryption](https://github.com/joegoldbeck/mongoose-encryption) if you are looking to encrypt the entire document.\n\n## How it works\n\nEncryption 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.\n\nFields 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.\n\n## Requirements\n\n- Node `>=6` (Use `2.3.4` for Node `>=4.4.7 && <=6.x.x`)\n- MongoDB `>=2.6.10`\n- Mongoose `>=4.0.0`\n\n## Installation\n\n`npm install mongoose-field-encryption --save-exact`\n\n## Security Notes\n\n- _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.\n- Additionally, store your encryption key offline somewhere safe. If you lose it, there is no way to retrieve your encrypted data.\n- 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.\n- 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.\n\n## Usage\n\n### Basic\n\nFor example, given a schema as follows:\n\n```js\nconst mongoose = require(\"mongoose\");\nconst mongooseFieldEncryption = require(\"mongoose-field-encryption\").fieldEncryption;\nconst Schema = mongoose.Schema;\n\nconst PostSchema = new Schema({\n  title: String,\n  message: String,\n  references: {\n    author: String,\n    date: Date\n  }\n});\n\nPostSchema.plugin(mongooseFieldEncryption, { fields: [\"message\", \"references\"], secret: \"some secret key\" });\n\nconst Post = mongoose.model(\"Post\", PostSchema);\n\nconst post = new Post({ title: \"some text\", message: \"hello all\" });\n\npost.save(function(err) {\n  console.log(post.title); // some text (only the message field was set to be encrypted via options)\n  console.log(post.message); // a9ad74603a91a2e97a803a367ab4e04d:93c64bf4c279d282deeaf738fabebe89\n  console.log(post.__enc_message); // true\n});\n```\n\nThe resulting documents will have the following format:\n\n```js\n{\n  _id: ObjectId,\n  title: String,\n  message: String, // encrypted salt and hex value as string, e.g. 9d6a0ca4ac2c80fc84df0a06de36b548:cee57185fed78c055ed31ca6a8be9bf20d303283200a280d0f4fc8a92902e0c1\n  __enc_message: true, // boolean marking if the field is encrypted or not\n  references: undefined, // encrypted object set to undefined\n  __enc_references: true, // boolean marking if the field is encrypted or not\n  __enc_references_d: String // encrypted salt and hex object value as string, e.g. 6df2171f25fd1d32adc4a4059f867a82:5909152856cf9cdb7dc32c6af321c8fe69390c359c6b19d967eaa6e7a0a97216\n}\n```\n\n`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.\n\nFrom 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._\n\nNote 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:\n\n```js\nPost.findOneAndUpdate({ _id: postId }, { $set: { message: \"snoop\", __enc_message: false } });\n```\n\nThe above also works for non-string fields. See changelog for more details.\n\nAlso 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.\n\n### Search over encrypted fields\n\nNote that in order to use this option a _fixed_ salt generator must be provided. See example as follows:\n\n```js\nconst messageSchema = new Schema({\n  title: String,\n  message: String,\n  name: String\n});\n\nmessageSchema.plugin(mongooseFieldEncryption, {\n  fields: [\"message\", \"name\"],\n  secret: \"some secret key\",\n  saltGenerator: function(secret) {\n    return \"1234567890123456\"; // should ideally use the secret to return a string of length 16\n  }\n});\n\nconst title = \"some text\";\nconst name = \"victor\";\nconst message = \"hello all\";\n\nconst Message = mongoose.model(\"Message\", messageSchema);\n\nconst messageToSave = new Message({ title, message, name });\nawait messageToSave.save();\n\n// note that we are only providing the field we would like to search with\nconst messageToSearchWith = new Message({ name });\nmessageToSearchWith.encryptFieldsSync();\n\n// `messageToSearchWith.name` contains the encrypted string text\nconst results = await Message.find({ name: messageToSearchWith.name });\n\n// results is an array of length 1 (assuming that there is only 1 message with the name \"victor\" in the collection)\n// and the message in the results array corresponds to the one saved previously\n```\n\n### Options\n\n- `fields` (required): an array list of the required fields\n- `secret` (required): a string cipher which is used to encrypt the data (don't lose this!)\n- `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.\n- `saltGenerator` (optional, default `const defaultSaltGenerator = secret => crypto.randomBytes(16);`): a function that should return either a `utf-8` encoded string that is 16 characters in length or a `Buffer` of length 16. This function is also passed the secret as shown in the default function example.\n\n### Static methods\n\nFor performance reasons, once the document has been encrypted, it remains so. The following methods are thus added to the schema:\n\n- `encryptFieldsSync()`: synchronous call that encrypts all fields as given by the plugin options\n- `decryptFieldsSync()`: synchronous call that decrypts encrypted fields as given by the plugin options\n- `stripEncryptionFieldMarkers()`: synchronous call that removes the encryption field markers (useful for returning documents without letting the user know that something was encrypted)\n\nMultiple calls to the above methods have no effect, i.e. once a field is encrypted and the `__enc_` marker field value is set to true then the ecrypt operation is ignored. Same for the decrypt operation. Of course if the field markers have been removed via the `stripEncryptionFieldMarkers()` call, then the encryption will be executed if invoked.\n\n### Searching\n\nTo enable searching over the encrypted fields the `encrypt` and `decrypt` methods have also been exposed.\n\n```js\nconst fieldEncryption = require('mongoose-field-encryption')\nconst encrypted = fieldEncryption.encrypt('some text', 'secret'));\nconst decrypted = fieldEncryption.decrypt(encrypted, 'secret')); // decrypted = 'some text'\n```\n\n## Development\n\nAs of version 3.0.5, one can setup a local development mongodb instance using docker:\n\n- copy `development/docker-compose-dev.yml` to `development/docker-compose.yml`\n- copy `development/init-mongo-dev.js` to `development/init-mongo.js`\n- run `docker-compose up` in the `development` folder\n\nFeel free to make changes to the default docker configuration as required.\n\n### Testing\n\n1. Install dependencies with `npm install` and [install mongo](http://docs.mongodb.org/manual/installation/) if you don't have it yet.\n2. Start mongo via `docker-compose up` under the `development` folder.\n3. Run tests with `npm run test:auth`. Additionally you can pass your own mongodb uri as an environment variable if you would like to test against your own database, for e.g. `URI='mongodb://username:password@127.0.0.1:27017/mongoose-field-encryption-test' npm test`\n\n### Publishing\n\n#### release-it\n\n`release-it patch,minor,major`\n\n#### Manual\n\n- `npm version patch,minor,major`\n- `npm publish`\n\n## Changelog\n\n### 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6\n\n- Update development dependencies, fix unit tests, no functionality affected\n- Add development db via docker (3.0.5)\n\n### 3.0.0\n\n- _BREAKING:_ Drop Node 4 support\n\n### 2.3.5\n\n- Update development dependencies, no functionality affected\n\n### 2.3.2, 2.3.3, 2.3.4\n\n- Update documentation, no functionality affected\n\n### 2.3.1\n\n- Update documentation, no functionality affected\n\n### 2.3.0\n\n- _FEATURE:_ Add provision for a custom salt generator, [PR #27](https://github.com/wheresvic/mongoose-field-encryption/pull/27). Note that by using a custom salt, _fixed_ search capability is now restored.\n\n### 2.2.0\n\n- Update dependencies, no functionality affected\n\n### 2.1.3\n\n- _FIX:_ Fix bug where decryption fails when the field in question is not retrieved, [PR #26](https://github.com/wheresvic/mongoose-field-encryption/pull/26).\n\n### 2.1.1\n\n- _FIX:_ Fix bug where data was not getting decrypted on a `find()`, [#23](https://github.com/wheresvic/mongoose-field-encryption/issues/23).\n\n### 2.0.0\n\n- _BREAKING:_ Use `cipheriv` instead of plain `cipher`, [#17](https://github.com/wheresvic/mongoose-field-encryption/issues/17).\n\n  Note that this might break any _fixed_ search capability as the encrypted values are now based on a random salt.\n\n  Also note that while this version maintains backward compatibility, i.e. decryption will automatically fall back to using the `aes-256-ctr` algorithm, any further updates will lead to the value being encrypted with the salt. In order to fully maintain backwards compatibilty, an new option `useAes256Ctr` has been introduced (default `false`), which can be set to `true` to continue using the plugin as before. It is highly recommended to start using the newer algorithm however, see issue for more details.\n\n### 1.2.0\n\n- _FEATURE:_ Added support for `findOneAndUpdate` [https://github.com/wheresvic/mongoose-field-encryption/pull/20](https://github.com/wheresvic/mongoose-field-encryption/pull/20)\n\n### 1.1.0\n\n- _FEATURE:_ Added support for mongoose 5 [https://github.com/wheresvic/mongoose-field-encryption/pull/16](https://github.com/wheresvic/mongoose-field-encryption/pull/16).\n- _FIX:_ Removed mongoose dependency, moved to `peerDependencies`.\n- Formatted source code using prettier.\n","readmeFilename":"README.md"}