Thursday, July 14, 2016

Encrypt / Decrypt data at db context

Override savechanges method and object materialized methods to automatically encrypt/decrypt data without manually doing it.
Here, the custom attribute [Encrypted] is used to mark a property as encrypted or secured data.
Use your way of security for encryption and decryption.

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

public class BaseDbContext : DbContext
    {
        public BaseDbContext() : base("mydbcontext")
        {
            ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += new ObjectMaterializedEventHandler(ObjectMaterialized);
        }

        public override int SaveChanges()
        {
            var contextAdapter = ((IObjectContextAdapter)this);

            contextAdapter.ObjectContext.DetectChanges();

            var pendingEntities = contextAdapter.ObjectContext.ObjectStateManager
                .GetObjectStateEntries(EntityState.Added | EntityState.Modified)
                .Where(en => !en.IsRelationship).ToList();

            foreach (var entry in pendingEntities) //Encrypt all pending changes
                EncryptEntity(entry.Entity);

            int result = base.SaveChanges();

            foreach (var entry in pendingEntities) //Decrypt updated entities for continued use
                DecryptEntity(entry.Entity);

            return result;
        }

        void ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
        {
            DecryptEntity(e.Entity);
        }

        private void EncryptEntity(object entity)
        {
            //Get all the properties that are encryptable and encrypt them
            var encryptedProperties = entity.GetType().GetProperties()
                .Where(p => p.GetCustomAttributes(typeof(Encrypted), true).Any(a => p.PropertyType == typeof(String)));
            foreach (var property in encryptedProperties)
            {
                string value = property.GetValue(entity) as string;
                if (!String.IsNullOrEmpty(value))
                {
                    property.SetValue(entity, SimpleEncrypt(value));
                }
            }
        }

        private void DecryptEntity(object entity)
        {
            //Get all the properties that are encryptable and decyrpt them
            var encryptedProperties = entity.GetType().GetProperties()
                .Where(p => p.GetCustomAttributes(typeof(Encrypted), true).Any(a => p.PropertyType == typeof(String)));

            foreach (var property in encryptedProperties)
            {
                string encryptedValue = property.GetValue(entity) as string;
                if (!String.IsNullOrEmpty(encryptedValue))
                {
                    Entry(entity).Property(property.Name).OriginalValue = SimpleDecrypt(encryptedValue);
                    Entry(entity).Property(property.Name).IsModified = false;
                }
            }
        }

        public string SimpleEncrypt(string value)
        {
            // your encryption logic
            return value;
        }

        public string SimpleDecrypt(string value)
        {
            // your decryption logic
            return value;

        }
    }

    public class Encrypted : Attribute { }

No comments:

Post a Comment