使用EF6插入数据时出错并始终加密

时间:2017-01-19 21:10:39

标签: entity-framework-6 azure-sql-database poco always-encrypted

我们遇到了EF6和始终加密功能的一些问题。

我认为我们需要在DBContext中设置一些内容,以便指示如何加密或解密列,但我无法找到实现此目的的方法。

我们已经有了一个ADO访问层,它与加密字段完美配合。我们宁愿使用EF而不是ADO。

症状是:

  1. 使用EF,我们可以查询数据。解密过程运行正常。
  2. 插入过程会抛出以下错误:
  3.   

    操作数类型冲突:varchar与加密的varchar(8000)不兼容(encryption_type =' DETERMINISTIC',encryption_algorithm_name =' AEAD_AES_256_CBC_HMAC_SHA_256&#39 ;, column_encryption_key_name =' CEK_Auto1' ,column_encryption_key_database_name =' Development_v2_qa')collat​​ion_name =' SQL_Latin1_General_CP1_CI_AS' **

    1. 使用where子句查询,使用加密字段,会抛出相同的错误。
    2. 使用的技术:

      • EF6与Poco实体。
      • 用于存储加密/解密主密钥的AzureKeyVault。
      • 使用SSL Certidicate对KeyVault进行身份验证
      • 连接字符串包含"列加密设置=启用;"
      • AzureSqlServer
      • FWK4.6
      • ADO

      我们有一些适用于ADO的代码。它适用于每个SqlConnection

      // Instantiate our custom AKV column master key provider.
      // It uses the GetToken function as the callback function to authenticate to AKV
      SqlColumnEncryptionAzureKeyVaultProvider akvprov = new SqlColumnEncryptionAzureKeyVaultProvider();
      akvprov.KeyVaultClient = SecureConfigurationManager.KeyVaultClient;
      // Register the instance of custom provider to SqlConnection
      Dictionary<string, SqlColumnEncryptionKeyStoreProvider> providers = new Dictionary<string, SqlColumnEncryptionKeyStoreProvider>();
      // "SqlColumnEncryptionAzureKeyVaultProvider.ProviderName" is the name of the provider. It must match the string we used when we created the column master key
      providers.Add(SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, akvprov);
      SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
      

2 个答案:

答案 0 :(得分:1)

是的,我刚刚发现同样的问题,需要添加

[Column(TypeName = "varchar(max)")]

在POCO类型之前为它工作的字段。 如果错误更清楚(如果NVARCHAR确实有效,那就更好了)

答案 1 :(得分:0)

我正在解决同样的问题。问题在于从C#到数据库的数据类型映射。并非所有长度对于使用Entity Framework的加密和varchars总是很重要,只有varchar(max)或varchar(8000)。我有所有实体框架使用azure密钥保险库处理所有数据类型,与您相同。下面的链接显示了如何使用内联SQL进行插入。我只使用实体框架,并希望我永远不必在内联sql工作,即使我可能不得不,如果我找不到一种方法来缩小加密所需的数据库存储开销,或者看起来像Stretch Db,也是SQL Server 2016中的另一个功能。感谢Jakub Szymaszek和Microsoft。

我承认并使我的所有数据类型都为varchar(max),并且它工作得很好。所以string = varchar(max)。奇怪的是加密中没有8000个字符,但可能分配了8000个字符。

“something1”在加密后插入: 0x0190F9D80C3F70890FB154F2123459506AD5BDA165333710D161ED80E42FCAFA882C66FF5B68E412B5F9EE11A9F308201D0AE2BD4032151398171FDBE2F3AEA20D

有关varchar(max)的有趣之处在于,除了插入的表之外,还有一个指向表或其他数据存储位置的链接,因此varchar(max)可能只占用显示的数量。 (我是开发者)

我的列和存储过程变量的dataType: [testVarChar] varchar COLLATE Latin1_General_BIN2 ENCRYPTED WITH(COLUMN_ENCRYPTION_KEY = [CEK_Auto1],ENCRYPTION_TYPE = Randomized,ALGORITHM ='AEAD_AES_256_CBC_HMAC_SHA_256')NOT NULL,

  

以SSN列为目标的参数的数据类型设置为ANSI(非Unicode)字符串,该字符串映射到char / varchar SQL Server数据类型。如果参数的类型设置为映射到nchar / nvarchar的Unicode字符串(String),则查询将失败,因为Always Encrypted不支持从加密的nchar / nvarchar值到加密的char / varchar值的转换。有关数据类型映射的信息,请参阅SQL Server数据类型映射。

https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/develop-using-always-encrypted-with-net-framework-data-provider