wheresvic / mongoose-field-encryption

A simple symmetric encryption plugin for individual fields. Dependency free, only mongoose peer dependency.
MIT License
74 stars 32 forks source link

Vewing database doesn't show encrypted fields #36

Closed Zeedinstein closed 4 years ago

Zeedinstein commented 4 years ago

When viewing my database use Robo 3T. The field that I have encrypted looks normal(No encryption). But I see the fields __enc_data & __enc_data_d (field I'm encrypting is called data). My data field stores an Array. Seems like the field is not actually being encrypted.

wheresvic commented 4 years ago

@Zeedinstein could you please post some sample code showing how you have configured the plugin and also what an example document looks like?

Could it be that another plugin is interfering with the encryption part?

wheresvic commented 4 years ago

Also you could clone mongoose-field-encryption and run the tests via npm test. Then check using Robo3T what the document in nestedfieldencryptions collection looks like.

Zeedinstein commented 4 years ago

Sure here is an example:

const mongoose = require('mongoose')
const Schema = mongoose.Schema
const autopopulate = require('mongoose-autopopulate')
const { fieldEncryption } = require("mongoose-field-encryption")

const FormSchema = new mongoose.Schema(
    {
        reference: { type: String },
        userId: { type: String },
        user: { type: Schema.Types.ObjectId, ref: 'User', autopopulate: true },
        userName: { type: String, default: null },
        fieldsCompleted: { type: Number, default: 0 },
        complete: { type: Boolean, default: false },
        data: {
            type: Schema.Types.Mixed,
        },
    },
    {
        timestamps: true,
    }
)

FormSchema.plugin(autopopulate)
FormSchema.plugin(fieldEncryption, {
    fields: ['data'],
    secret: 'AVerySecretThing',
})

let Form = mongoose.model('Form', FormSchema)

I will try cloning as well

Zeedinstein commented 4 years ago

Okay so I built a test using what is already there.

it("should save a document with a MixedType Object with an Array", function(done) {
    // given
    const formSchema = new Schema({
      title: String,
      message: String,
      data: {
        type: Schema.Types.Mixed
      }
    });

    formSchema.plugin(mongooseFieldEncryption, {
      fields: ["data"],
      secret: "some secret key"
    });

    const Form = mongoose.model("form", formSchema);
    const form = new Form({
      title: "some text",
      message: "hello all",
      data: [{ name: "field", value: "very secret" }]
    });

    // when
    form.save(function(err) {
      // then
      if (err) {
        return done(err);
      }

      expect(form.title).to.equal("some text");
      expect(form.__enc_data).to.be.true;

      console.dir(form.toObject());

      done();
    });
  });

It outputs:

{
  _id: ObjectID {
    _bsontype: 'ObjectID',
    id: Buffer [Uint8Array] [
       94,  24, 91, 148, 213,
       11, 198, 97,  95,  34,
      150, 222
    ]
  },
  title: 'some text',
  message: 'hello all',
  __enc_data_d: '7c440c3608c31d68f51d86c66c33e678:05577c2c12266c96b0d6d95e26ad1a7308b6e282915d7842931dd486e09ac076ac865bc95ccde6f354b8705db4a03060',
  __enc_data: true,
  __v: 0
}

But now we don't have the data field there, we just have the __enc fields. Not sure if this is correct ?

wheresvic commented 4 years ago

@Zeedinstein yes this is correct behaviour - as you can see from the test - the data field has been encrypted into __enc_data_d and the field itself has been removed. If you think about it, leaving the data field there would create confusion.