本文针对从启用了 Always Encrypted 的数据库访问数据时导致 .NET Framework 4.6.2 客户端应用程序失败的问题提供了解决方法。
原始产品版本: SQL Server 2016、SQL Server 2017
原始 KB 数: 3204545
现象
你有一个客户端应用程序,该应用程序使用 Microsoft .NET Framework 4.6.2 中包含的用于 Microsoft SQL Server (Sqlclient)的 .NET Framework 数据提供程序。 使用此应用程序连接到在 Windows 或 Microsoft Azure SQL 数据库 Microsoft SQL Server 2016、SQL Server 2017 上运行的已启用 Always Encrypted 的数据库。
尝试从 启用了 Always Encrypted 的数据库解密记录时,会收到类似于以下错误的间歇性错误消息:
解密失败。 加密列加密密钥的最后 10 个字节为:7E-0B-E6-D3-39-CE-35-86-2F-AA。密码文本的前 10 个字节为:01-C3-D7-39-33-2F-E6-44-C3-B1。指定的密码文本具有无效的身份验证标记。
出现此问题时,针对受 Always Encrypted 设置保护的列的查询可能会显示不正确的结果,例如返回的记录太少。 反过来,这可能会触发不正确的行为。 例如,客户端应用程序尝试插入缺失值或运行其他更新进程,这些进程会创建其他错误或导致数据库中的数据不一致。
解决方法
若要解决此问题,请从 Microsoft安全公告 MS16-155 安装安全更新。
解决方法
重要
如果客户端应用程序通过 Microsoft Azure App 服务 上的Web 应用托管,则客户端会自动使用 .NET Framework 4.6.2。 因此,可能会遇到“症状”部分中提到的问题。 在此方案中,只能在本部分中使用方法 2 解决方法(“关闭列加密”),直到发布了此问题的修补程序。
若要解决此问题,请根据需要遵循以下准则:
.NET 客户端尚未升级到版本 4.6.2
在“症状”部分中提到的环境中,建议不要升级到 .NET Framework 4.6.2,直到此问题得到解决。 此问题不会影响驱动程序的早期版本。
.NET 客户端已升级到 4.6.2
使用下列方法之一:
方法 1:回滚 .NET Framework 版本
从系统的托管客户端应用程序中卸载 .NET Framework 4.6.2。 这强制应用程序使用未遇到此问题的旧版 NET Framework 数据提供程序 for SQL Server。 为此,请按照下列步骤进行操作:
- 在控制面板中,打开“程序”项,然后选择“程序和功能”。
- 选择“ 查看已安装的更新”,然后卸载 windows KB3120737 Microsoft更新。
注意
建议卸载任何版本的 .NET Framework 后,测试依赖于 .NET Framework 的应用程序。 如果卸载依赖的 .NET Framework 版本,这些应用程序可能无法正常工作。
方法 2:关闭列加密密钥缓存
如果无法回滚 .NET Framework 安装,请关闭列加密密钥 (CEK) 缓存。 为此, 请将客户端应用程序中的 SqlConnection.ColumnEncryptionKeyCacheTtl 属性 设置为 0。 例如,运行以下代码在 C# 应用程序中禁用列加密:
System.Data.SqlClient.SqlConnection.ColumnEncryptionKeyCacheTtl = TimeSpan.Zero
使用任一方法后,请验证在表扫描(如具有 Always Encrypted 的 SELECT * FROM <表)期间,该错误是否在 SSMS 中的查询窗口中通过具有列加密设置=Enabled 的数据库连接在连接字符串中再次出现。> 运行此类扫描会验证正确的加密。
重要
在验证扫描期间遇到“症状”部分中描述的问题的用户应联系sqlalwaysencrypted@microsoft.com。 支持团队可以帮助恢复受此 bug 影响的所有以前加密的行。 此 bug 不会导致永久数据丢失。
参考
用于 Always Encrypted 的 .NET Framework 4.6.2 客户端驱动程序导致间歇性故障解密各个行