A more secure and efficient solution involves using a hybrid approach with a master key and user-specific keys. Here’s an improved approach:

Approach

  1. Master Key : A master key is used to encrypt and decrypt user-specific keys.
  2. User-Specific Key : Each user has a unique key used to encrypt their emails.
  3. Key Encryption Key (KEK) : User-specific keys are encrypted with the master key and stored securely.
  4. Password Change : When a user changes their password, only the user-specific key needs to be re-encrypted with the new password-derived key, not the entire email data.

Implementation Steps

  1. Generate a Master Key : This key will be used to encrypt/decrypt user-specific keys.
  2. Encrypt User-Specific Keys with the Master Key : Store the encrypted user-specific keys in the database.
  3. Use Password-Derived Keys to Encrypt/Decrypt Data : User-specific keys are derived from user passwords for encrypting/decrypting emails.
  4. Handle Password Changes : When a user changes their password, only re-encrypt the user-specific key.

Detailed Implementation

Step 1: Setup Master Key

Generate and securely store a master key. For simplicity, you can use an environment variable:

export MASTER_KEY = <your-secure-master-key>

Step 2: Update User Model

Modify the User model to include encrypted user-specific keys:

// models/User.js
const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    unique: true,
  },

  passwordHash: {
    type: String,
    required: true,
  },

  encryptedUserKey: {
    type: String,
    required: true,
  },
});

module.exports = mongoose.model("User", userSchema);

Step 3: Update Crypto Utilities