{"id":51244836,"url":"https://github.com/tsmx/mongoose-aes-encryption-migrate","last_synced_at":"2026-06-29T03:31:53.347Z","repository":{"id":353412470,"uuid":"1219310888","full_name":"tsmx/mongoose-aes-encryption-migrate","owner":"tsmx","description":"CLI migration tool to encrypt existing MongoDB collections for use with mongoose-aes-encryption","archived":false,"fork":false,"pushed_at":"2026-06-10T21:12:17.000Z","size":718,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-10T23:09:33.902Z","etag":null,"topics":["aes-256-gcm","field-encryption","migration","mongodb","mongoose"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tsmx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-23T18:42:54.000Z","updated_at":"2026-06-10T21:12:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tsmx/mongoose-aes-encryption-migrate","commit_stats":null,"previous_names":["tsmx/mongoose-aes-encryption-migrate"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tsmx/mongoose-aes-encryption-migrate","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsmx%2Fmongoose-aes-encryption-migrate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsmx%2Fmongoose-aes-encryption-migrate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsmx%2Fmongoose-aes-encryption-migrate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsmx%2Fmongoose-aes-encryption-migrate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tsmx","download_url":"https://codeload.github.com/tsmx/mongoose-aes-encryption-migrate/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tsmx%2Fmongoose-aes-encryption-migrate/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34912252,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes-256-gcm","field-encryption","migration","mongodb","mongoose"],"created_at":"2026-06-29T03:31:53.249Z","updated_at":"2026-06-29T03:31:53.341Z","avatar_url":"https://github.com/tsmx.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n![npm version](https://img.shields.io/npm/v/mongoose-aes-encryption-migrate)\n![node version](https://img.shields.io/node/v/mongoose-aes-encryption-migrate)\n[![Build Status](https://img.shields.io/github/actions/workflow/status/tsmx/mongoose-aes-encryption-migrate/git-build.yml?branch=master)](https://github.com/tsmx/mongoose-aes-encryption-migrate/actions/workflows/git-build.yml)\n[![Coverage Status](https://coveralls.io/repos/github/tsmx/mongoose-aes-encryption-migrate/badge.svg?branch=master)](https://coveralls.io/github/tsmx/mongoose-aes-encryption-migrate?branch=master)\n\n# mongoose-aes-encryption-migrate\n\nCLI migration tool for [mongoose-aes-encryption](https://github.com/tsmx/mongoose-aes-encryption) for existing databases in plaintext or using other Mongoose encryption plugins.\n\nSupports migration for the following paths:\n\n| Mode | Source plugin | Source encryption |\n|---|---|---|\n| `plaintext` | No encryption — plain text fields | none |\n| `mongoose-encryption` | [mongoose-encryption](https://github.com/joegoldbeck/mongoose-encryption) | AES-CBC |\n| `mongoose-field-encryption` | [mongoose-field-encryption](https://github.com/wheresvic/mongoose-field-encryption) | AES-CBC |\n\n\u003e **Always back up your database before running a migration.**\n\n---\n\n## Installation\n\n```bash\nnpm install -g mongoose-aes-encryption-migrate\n```\n\nOr use without installing via `npx`:\n\n```bash\nnpx mongoose-aes-encryption-migrate --help\n```\n\n---\n\n## CLI usage\n\n### Mode 1 — Plain-text to encrypted\n\nUse this when you have added `encrypted: true` to fields in an existing Mongoose schema and need to encrypt all existing documents that still hold plain-text values.\n\n```bash\nmongoose-aes-encryption-migrate \\\n  --uri         mongodb://localhost:27017/mydb \\\n  --collection  users \\\n  --mode        plaintext \\\n  --key         9af7d400be4705147dc724db25bfd2513aa11d6013d7bf7bdb2bfe050593bd0f \\\n  --fields      name,email,salary\n```\n\nThe tool is **idempotent** — documents whose fields are already encrypted are detected and skipped automatically. Safe to re-run.\n\n---\n\n### Mode 2 — From mongoose-encryption\n\nUse this when migrating from [mongoose-encryption](https://github.com/joegoldbeck/mongoose-encryption), which stores all encrypted fields bundled together in a single `_ct` Binary field per document.\n\n```bash\nmongoose-aes-encryption-migrate \\\n  --uri           mongodb://localhost:27017/mydb \\\n  --collection    users \\\n  --mode          mongoose-encryption \\\n  --key           9af7d400be4705147dc724db25bfd2513aa11d6013d7bf7bdb2bfe050593bd0f \\\n  --source-key    \u003cbase64-encoded encryptionKey from mongoose-encryption\u003e \\\n  --fields        name,email \\\n  --plaintext-fields salary\n```\n\n**Important:** `mongoose-encryption` bundles multiple fields into a single `_ct` blob. Every field found inside that blob must be explicitly accounted for:\n\n- `--fields` — fields to re-encrypt individually with `mongoose-aes-encryption`\n- `--plaintext-fields` — fields to restore as unencrypted plaintext\n\nIf any field inside `_ct` is not covered by either flag, the tool **aborts at pre-flight** and lists the unaccounted fields along with suggested corrected commands. No data is lost or changed.\n\nAfter migration, `_ct` and `_ac` are removed from every document.\n\n---\n\n### Mode 3 — From mongoose-field-encryption\n\nUse this when migrating from [mongoose-field-encryption](https://github.com/wheresvic/mongoose-field-encryption), which stores each field as a per-field AES-256-CBC string in the format `\u003csalt-hex\u003e:\u003cciphertext-hex\u003e` alongside `__enc_\u003cfield\u003e` boolean marker fields.\n\n```bash\nmongoose-aes-encryption-migrate \\\n  --uri         mongodb://localhost:27017/mydb \\\n  --collection  users \\\n  --mode        mongoose-field-encryption \\\n  --key         9af7d400be4705147dc724db25bfd2513aa11d6013d7bf7bdb2bfe050593bd0f \\\n  --secret      \"the secret string used with mongoose-field-encryption\" \\\n  --fields      name,email,salary\n```\n\nAfter migration, the `__enc_\u003cfield\u003e` boolean markers and any `__enc_\u003cfield\u003e_d` data fields (used for non-string types) are removed from every document.\n\nDocuments where the `__enc_\u003cfield\u003e` marker is `false` or absent are skipped (field is already plaintext).\n\n---\n\n## All options\n\n| Option | Required | Default | Description |\n|---|---|---|---|\n| `--uri` | yes | — | MongoDB connection string, must include database name |\n| `--collection` | yes | — | Collection name to migrate |\n| `--mode` | yes | — | `plaintext`, `mongoose-encryption`, or `mongoose-field-encryption` |\n| `--key` | yes | — | 64-character hex target encryption key |\n| `--fields` | yes | — | Comma-separated field paths to encrypt |\n| `--plaintext-fields` | mode 2 only | — | Comma-separated fields from `_ct` to restore as plaintext |\n| `--source-key` | mode 2 only | — | base64 `encryptionKey` used with `mongoose-encryption` |\n| `--secret` | mode 3 only | — | Secret string used with `mongoose-field-encryption` |\n| `--algorithm` | no | `aes-256-gcm` | Target algorithm: `aes-256-gcm` or `aes-256-cbc` |\n| `--batch-size` | no | `100` | Number of documents to process per batch |\n| `--dry-run` | no | `false` | Probe and report without writing any changes |\n\n\u003e When running without `--dry-run`, the tool will prompt for confirmation before writing any changes. Answer `y` to proceed. Default answer is `n` (abort).\n\n---\n\n## Dry-run mode\n\nAdd `--dry-run` to any command to see what would happen without touching the database:\n\n```bash\nmongoose-aes-encryption-migrate \\\n  --uri mongodb://localhost:27017/mydb \\\n  --collection users \\\n  --mode plaintext \\\n  --key  9af7d400be4705147dc724db25bfd2513aa11d6013d7bf7bdb2bfe050593bd0f \\\n  --fields name,email \\\n  --dry-run\n```\n\n---\n\n## Error handling\n\nIf a document fails to update (e.g. due to a write conflict), the tool pauses and asks:\n\n```\n  Error processing document _id=64a3f...: \u003cerror message\u003e\n? What do you want to do?\n  \u003e Skip this document and continue\n    Abort the migration\n```\n\nSkipped document IDs are reported in the final summary. You can re-run the tool afterward — already-migrated documents are skipped automatically.\n\n---\n\n## Programmatic API\n\nFor use in custom migration scripts or CI pipelines. Errors throw immediately (no interactive prompts).\n\n```js\nconst {\n    plaintextToEncrypted,\n    mongooseEncryptionToEncrypted,\n    mongooseFieldEncryptionToEncrypted\n} = require('mongoose-aes-encryption-migrate');\n\n// Mode 1 — plain text\nconst result = await plaintextToEncrypted({\n    uri:        'mongodb://localhost:27017/mydb',\n    collection: 'users',\n    fields:     ['name', 'email', 'salary'],\n    key:        '9af7d400be4705147dc724db25bfd2513aa11d6013d7bf7bdb2bfe050593bd0f',\n    algorithm:  'aes-256-gcm',   // optional, default\n    batchSize:  100,              // optional, default\n    dryRun:     false             // optional, default\n});\n// result: { migrated: 998, skipped: 2, errors: 0 }\n\n// Mode 2 — mongoose-encryption\nconst result2 = await mongooseEncryptionToEncrypted({\n    uri:             'mongodb://localhost:27017/mydb',\n    collection:      'users',\n    fields:          ['name', 'email'],\n    plaintextFields: ['salary'],\n    key:             '9af7d400be4705147dc724db25bfd2513aa11d6013d7bf7bdb2bfe050593bd0f',\n    sourceKey:       '\u003cbase64 encryptionKey\u003e',\n    dryRun:          false\n});\n\n// Mode 3 — mongoose-field-encryption\nconst result3 = await mongooseFieldEncryptionToEncrypted({\n    uri:        'mongodb://localhost:27017/mydb',\n    collection: 'users',\n    fields:     ['name', 'email', 'salary'],\n    secret:     'the secret string used with mongoose-field-encryption',\n    key:        '9af7d400be4705147dc724db25bfd2513aa11d6013d7bf7bdb2bfe050593bd0f',\n    dryRun:     false\n});\n```\n\nAll functions return `Promise\u003c{ migrated: number, skipped: number, errors: number }\u003e`.\n\n---\n\n## How each source plugin is migrated\n\n### mongoose-encryption\n\n`mongoose-encryption` stores all encrypted fields together in a single `_ct` BSON Binary field:\n\n```\n_ct layout:  [ version (1 byte) | IV (16 bytes) | AES-256-CBC ciphertext ]\n             ciphertext decrypts to: JSON.stringify({ name: \"Joe\", email: \"...\", salary: 50000 })\n```\n\nThe migration tool:\n1. Decrypts `_ct` using the AES-256-CBC `encryptionKey` provided as `--source-key` (base64)\n2. Re-encrypts each field in `--fields` individually using `mongoose-aes-encryption`'s wire format\n3. Restores fields in `--plaintext-fields` as unencrypted values\n4. Writes `$set` of all new field values and `$unset` of `_ct` and `_ac` in a single atomic update per document\n\nDocuments without a `_ct` field are skipped (already migrated or never encrypted).\n\n### mongoose-field-encryption\n\n`mongoose-field-encryption` stores each encrypted field in-place as:\n\n```\n\u003c16-byte-salt-hex\u003e:\u003cciphertext-hex\u003e\n```\n\nUsing AES-256-CBC with a key derived from the user's secret via `SHA-256(secret).slice(0, 32 bytes)`. A boolean marker `__enc_\u003cfieldname\u003e: true` marks encrypted fields. Non-string types are additionally stored in a `__enc_\u003cfieldname\u003e_d` field with the original field set to `undefined`.\n\nThe migration tool:\n1. Checks the `__enc_\u003cfield\u003e` marker — if `false` or absent, the field is plaintext and skipped\n2. Derives the AES key from the `--secret` using the same SHA-256 method\n3. Decrypts each field value (or `__enc_\u003cfield\u003e_d` for non-string types)\n4. Re-encrypts with `mongoose-aes-encryption`'s wire format\n5. Writes `$set` of new ciphertext values and `$unset` of all `__enc_*` marker and data fields\n\n**Note on non-string field types:** `mongoose-field-encryption` stores non-string values (numbers, booleans, dates) as `JSON.stringify`'d strings in a separate `__enc_\u003cfield\u003e_d` field. After migration, these values are stored as encrypted strings. If your Mongoose schema defines those fields with a non-string type (e.g. `Number`, `Boolean`, `Date`), Mongoose will automatically cast the decrypted string back to the correct type on read. If you access the collection via the raw MongoDB driver without Mongoose, you will need to cast the values manually after decryption.\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsmx%2Fmongoose-aes-encryption-migrate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftsmx%2Fmongoose-aes-encryption-migrate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftsmx%2Fmongoose-aes-encryption-migrate/lists"}