【问题标题】:How do I encrypt data in Entity Framework Code First?如何在 Entity Framework Code First 中加密数据?
【发布时间】:2014-04-08 17:28:39
【问题描述】:

我一直在尝试并未能找到一种使用 Entity Framework Code First 加密 SQL 数据的好方法。我必须以我在 Azure 中托管并且无权访问本机 SQL 加密作为开头。

SecurEntity 获取一个页面,我已经完全实现了一种利用 SaveChanges 和 ObjectMaterialized 来处理实体的加密/解密的方法,但在测试中我发现这太不可靠了。

这里是一些实现的示例:

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

我看过其他通过辅助属性手动加密/解密的帖子,如下所示:

public Value { get; set; }

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

这肯定会奏效,但我发现这种方法……不太理想。使用这种方法时,所有开发人员都必须遍历所有加密属性以找到他们可以使用的属性。

最理想的解决方案是让我能够在数据访问级别覆盖每个值的获取/设置。有没有办法做到这一点?如果没有,我如何使用 Entity Framework - Code First 实现数据加密,以便易于维护和使用?

【问题讨论】:

  • 请注意,SecurEntity 的当前实现有一个致命的安全漏洞,这意味着从证书生成的密钥实际上从未使用过。有关快速而肮脏的修复,请参阅securentity.codeplex.com/workitem/7376

标签: c# entity-framework azure encryption ef-code-first


【解决方案1】:

我有好消息。我在使用 SaveChanges/ObjectMaterialized 方法时遇到的不稳定性是由于 DetectChanges() 直到 DbContext 实际执行保存才被调用。

在我从ObjectStateManager 中提取添加/修改的记录之前,我可以通过调用DetectChanges() 来解决此问题。这清除了任何导致加密行为不一致的对象状态异常。

生成的代码是:

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

编辑 - 添加了一个示例 DataContext 以查看我用于加密所有实体的端到端解决方案。注意:您不必使用自定义属性来加密属性。 Source

【讨论】:

  • 有没有办法覆盖所有属性 GET 方法来解密它们?我不想在每个对象的基础上这样做,我们可以在全局级别上覆盖它,然后循环属性并解密任何字符串属性吗?
  • 我不确定您要的是什么,但可以在 EntityFramework 中保存/检索所有对象时修改它们的属性。这正是我的示例代码中的EncryptEntity DecryptEntity 所做的。我会将这两种方法添加到我的答案中以供参考。
  • 您可以分享您的 EncryptionService 版本吗?如果没有,你能给我一些关于如何实现这一目标的指导吗?我已经尝试过寻找这个,但在存储加密密钥的位置等方面没有取得太大的成功。
  • @parth-shah,我将发布我正在使用的完整方法的示例。但是,加密密钥存储是其自身的问题。我使用Azure's app config settings feature 设置生产加密密钥。但是有一个whole industry that provides secure encryption key storage solutions。这是一个非常困难的问题,因为只要可信实体可以访问数据,黑客也有可能获取数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 2011-08-01
相关资源
最近更新 更多