帶有Entity Framework的加密列

c# encryption entity entity-framework mysql

有人想出一個通過實體框架4從db中提取加密值的好方法嗎?

我有一個MySql數據庫,其中一些列使用des_encrypt加密,並且需要能夠盡可能簡單地獲取這些值,當然還有更新和插入它們。

我覺得很奇怪,在EF中似乎沒有建立對此的支持。即使是我們自己構建的ORM系統也支持這一點。我們只為加密的每個字段添加“加密”註釋,ORM工具將在查詢中添加des_decrypt(列)和des_encrypt(列)。

任何人?

一般承認的答案

IMO你應該將它放入數據庫之前進行加密並將其存儲為二進制數據。然後,您可以輕鬆地使用EF獲取byte[]

編輯:如果您使用存儲過程執行所有des_encryptdes_decrypt以及為您selects/inserts/deletes ,該怎麼辦?那麼EF還會為你做映射嗎?


熱門答案

這是@TheCloudlessSky提出的答案的實現示例。我認為這將有助於任何想知道如何實施它的人。

我正在使用現有的數據庫,因此我自動生成了基本的模型類。

自動生成的User.cs:

namespace MyApp.Model 
{
    public partial class User
    {
        public int UserId { get; set; }
        public byte[] SSN { get; set; }
        ...
    }
}

我創建了自己的User.cs. (注意它與自動生成的User.cs位於相同的命名空間中,並且沒有編譯器錯誤,因為自動生成的User.cs被聲明為部分類 !而且,我自己的User.cs不能與auto-在同一個文件夾中因文件名衝突而生成User.cs!)

namespace MyApp.Model 
{
    public partial class User
    {
        public string DecryptedSSN { get; set; }
        ...
    }
}

現在每當我從我的DbContext中檢索User時,我將看到自動生成的類中定義的所有屬性以及我的增強類中定義的屬性。

這是我的UserRepository.cs的一個實現:

namespace MyApp.Model
{
    public interface IUserRepository 
    {
        User Get(int userId);
        ...
    }

    public class UserRepository : IUserRepository
    {
        public User GetById(int userId)
        {
            using (var dataContext = MyDbContext())
            {
                var user = dataContext.Users.Find(u => u.UserId == userId);
                var decryptedSSNResult = dataContext.Decrypt(u.SSN);
                user.DecryptedSSN = decryptedSSNResult.FirstOrDefault();
                return user;
            }
        }
    }
}

現在您可能想知道我是從哪裡獲得MyDbContext.Decrypt()的?

這不是自動為您生成的。但是,您可以將此存儲過程導入到自動生成的Model.Context.cs文件中。 (官方EntityFramework文章:如何:導入存儲過程(實體數據模型工具)在http://msdn.microsoft.com/en-us/library/vstudio/bb896231(v=vs )中詳細記錄了此過程.100).aspx

如果您不知道最終結果應該是什麼樣的,這裡是我在Model.Context.cs中自動生成的內容:

namespace MyApp.Model
{
    // using statements found here

    public partial class MyDbContext : DbContext
    {
        public MyDbContext()
            : base("name = MyDbContext")
        { }

        public virtual ObjectResult<string> Decrypt(byte[] encryptedData)
        {
            var encryptedDataParameter = encryptedData != null ? 
                            new ObjectParameter("encryptedData", encryptedData) :
                            new ObjectParameter("encryptedData", typeof(byte[]));

            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<string>("Decrypt", encryptedDataParameter);
        }

        // similar function for Encrypt 
    }
}

這就是我的Decrypt存儲過程的樣子:

CREATE PROCEDURE decrypt
    @encryptedData VARBINARY(8000)
AS
BEGIN
    OPEN SYMMETRIC KEY xxx_Key DECRYPTION BY CERTIFICATE xxx_Cert;

    SELECT CAST(DECRYPTIONBYKEY(@encryptedData) AS NVARCHAR(MAX)) AS data;

    CLOSE ALL SYMMETRIC KEYS;
END;
GO

性能注意事項

現在我已經向您展示了@TheCloudlessSky給出的答案實現,我想快速強調一些與性能相關的要點。

1)每次檢索用戶對象時,都會對數據庫進行2次旅行,而不是1次。檢索對象的第一次旅行;解密SSN的第二次旅行。如果您不小心,這可能會導致性能問題。

建議 :不要自動解密加密字段!在上面顯示的示例中,我在檢索用戶對象時解密了SSN。我這樣做只是為了演示目的!問自己每次檢索用戶是否真的需要SSN。如果可能的話,選擇懶惰的解密而不是急切的解密!

2)雖然我沒有證明這一點,但每次創建/更新用戶對象時,也會有2次訪問數據庫。加密SSN的第一次旅行;插入物體的第二次旅行。如果您不小心,這可能會導致性能問題。

建議 :注意這種性能影響,但不要將SSN的加密和保存委託為不同的方法。將其全部保存在一個操作中,否則您可能會忘記完全保存它。因此,創建/更新的建議與檢索相反:選擇對延遲加密的急切加密!



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因