簡體   English   中英

使用 EF Core 3 解密數據

[英]Decrypting data using EF Core 3

我正在嘗試了解如何使用 EF Core 解密使用對稱密鑰加密的列數據。 在 SQL 服務器中,我會使用這些命令來獲取我的數據:

OPEN SYMMETRIC KEY My_Key DECRYPTION BY CERTIFICATE myCert;
SELECT  CONVERT(char, DecryptByKey(soc_sec_no))
FROM MyDatabase WHERE arid_identifier=0001882

如何從 EF Core 3 執行此操作? 我從 Entity Framework 6 (non-core) 看到很多關於如何做到這一點的文章,我確實找到了這個問題,但代碼對我不起作用。

我從https://github.com/tkhadimullin/ef-core-custom-functions/tree/feature/ef-3.1-version開始。

我已將更改放在https://github.com/xanatos/ef-core-custom-functions/tree/feature/ef-3.1-version上。 請注意,有三個提交,一個用於 EF Core 3.1,一個用於 EF Core 3.1.11(無需更改),一個用於 EF Core 5.0.2(需要進行一些更改)。

可悲的是,我必須糾正代碼中的各種小錯誤。 關於OPEN SYMMETRIC KEY的部分其實是沒有測試過的,被作者注釋掉了。

必要的更改:

class 回購:

需要一個事務來將各種 SQL 命令放在一起。 參數索引錯誤。 我添加了一些針對對稱密鑰名稱和密碼的注入攻擊的保護(可能沒用,因為這兩件事應該受到很好的保護)

public IEnumerable<Model> GetAllById(int id)
{
    // Transaction to keep together the two ExecuteSqlRaw with the query
    DbContext.Database.BeginTransaction();

    DbContext.Database.ExecuteSqlRaw($"DECLARE @Open NVARCHAR(MAX) = N'OPEN SYMMETRIC KEY ' + QUOTENAME(@p0, '[') + ' DECRYPTION BY PASSWORD = ' + QUOTENAME(@p1, '''') + N';'; EXEC sp_executesql @Open", SymmetricKeyName, SymmetricKeyPassword);

    var filteredSet = Set.Include(x => x.Table2)
        .Where(x => x.Id == id)
        .Where(x => x.Table2.IsSomething)
        .Select(m => new Model
        {
            Id = m.Id,
            //Decrypted = EF.Functions.Decrypt(SymmetricKeyPassword, m.Encrypted).ToString(),
            Decrypted = EF.Functions.DecryptByKey(m.Encrypted2).ToString(), // since the key's opened for session scope - just relying on it should do the trick
            Table2 = m.Table2,
            Encrypted = m.Encrypted,
        }).ToList();

    DbContext.Database.ExecuteSqlRaw($"DECLARE @Close NVARCHAR(MAX) = N'CLOSE SYMMETRIC KEY ' + QUOTENAME(@p0, '[') + ';'; EXEC sp_executesql @Close", SymmetricKeyName);

    DbContext.Database.CommitTransaction();

    return filteredSet;
}

class TranslateImpl:

修復了處理 arguments 的一些問題(2 個 arguments 並不總是存在,如果只有一個則方法崩潰)

public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments)
{
    if (method == _encryptMethod)
    {
        var args = new[] { arguments[1], arguments[2] }; // cut the first parameter from extension function
        return _expressionFactory.Function(instance, "ENCRYPTBYPASSPHRASE", args, typeof(byte[]));
    }

    if (method == _decryptMethod)
    {
        var args = new[] { arguments[1], arguments[2] }; // cut the first parameter from extension function
        return _expressionFactory.Function(instance, "DECRYPTBYPASSPHRASE", args, typeof(byte[]));
    }

    if (method == _decryptByKeyMethod)
    {
        var args = new[] { arguments[1], }; // cut the first parameter from extension function
        return _expressionFactory.Function(instance, "DECRYPTBYKEY", args, typeof(byte[]));
    }

    return null;
}

腳本 dbSchema.sql

該腳本現在可以以兩種不同的方式加密文本(密碼或對稱密鑰)

CREATE SYMMETRIC KEY [TestKeyWithPassword] WITH ALGORITHM = AES_128 ENCRYPTION BY PASSWORD = 'TestPassword'
GO
OPEN SYMMETRIC KEY [TestKeyWithPassword] DECRYPTION BY PASSWORD = 'TestPassword'
GO
INSERT [dbo].[Models] ([Id], [Encrypted], [Table2Id]) 
VALUES (
    1, 
    --ENCRYPTBYPASSPHRASE('TestPassword', 'Encrypted with Passphrapse'), 
    ENCRYPTBYKEY(key_GUID('TestKeyWithPassword'), 'Encrypted with Symmetric Key With Password'), 
    1)

關於.ToString() 的重要說明

Decrypt / DecryptByKey之后有一個.ToString() 它由 EF Core 轉換為CONVERT(VARCHAR(100), ...) 如果你想要一些不同的東西,你必須創建一些DBFunctions來做到這一點(這很簡單,以DbFunctionsExtensions.Encrypt ,在我的 git 中完成)

關於保存時加密的重要說明

在所有這些中,我不確定您將如何實現加密部分。 雖然您對 EF Core 生成的SELECT有一些控制權,但您對INSERT / UPDATE的控制權要小得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM