How do I encrypt data in Entity Framework Code First?

azure c# ef-code-first encryption entity-framework

Question

I've been attempting to use the Entity Framework Code First to encrypt SQL data, but I've been unsuccessful. I should note at the outset that because I host in Azure, I am unable to use native SQL encryption.

I fully constructed an approach that uses SaveChanges and ObjectMaterialized to manage the encryption and decrypting of the entities, taking a page from SecurEntity, however during testing I realized that this has been way too unreliable to employ.

An example of some of the implementation is given below:

public override int SaveChanges()
{
    var pendingEntities = ((IObjectContextAdapter)this).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);
}

Other posts that manually encrypt/decrypt using secondary attributes have been spotted by me, such this:

public Value { get; set; }

[NotMapped]
public DecryptedValue
{
    get { return Decrypt(this.Value); }
    set { this.Value = Encrypt(value); }
}

This will undoubtedly work, however I think that this strategy is... less than perfect. This method requires developers to sort through all of the encrypted attributes to determine which ones they may utilize.

The best option would be for me to have control over each value's getting or setting at the data-access level. Exists a way to accomplish this? If not, how can I use Entity Framework - Code First to develop data encryption that is simple to manage and use?

1
13
4/8/2014 5:28:39 PM

Accepted Answer

I've got good news. The SaveChanges/ObjectMaterialized method was causing me to experience instability becauseDetectChanges() is not called until the DbContext completes the save operation.

By phoning, I was able to resolve this.DetectChanges() prior to obtaining the entries that have been Added/Modified from theObjectStateManager This resolved any object state anomalies causing erratic encryption behavior.

The final code is as follows:

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;
}

26 zzz-zzz - I've included a sample DataContext so you can see my end-to-end approach of encrypting every entity. To encrypt properties, you don't need to utilize a special attribute. Source

11
11/21/2014 4:31:13 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow