【问题标题】:SQL Server 2005 Encryption, asp.net and stored proceduresSQL Server 2005 加密、asp.net 和存储过程
【发布时间】:2010-09-08 18:20:30
【问题描述】:

我需要使用 SQL Server 2005、asp.net 和 ado.net 编写一个 Web 应用程序。此应用程序中存储的大部分用户数据都必须加密(读取 HIPAA)。

过去对于需要加密的项目,我在应用程序代码中进行了加密/解密。但是,这通常用于加密密码或信用卡信息,因此在几个表中只有少数列。对于这个应用程序,多个表中的更多列需要加密,因此我怀疑将加密职责推入数据层会更好,特别是考虑到 SQL Server 2005 对多种加密类型的本机支持。 (如果有人有真实的经验证据,我可能会被说服。)

我咨询过 BOL,而且我非常擅长使用 google。所以我不想要在线文章或 MSDN 文档的链接(我可能已经阅读过)。

到目前为止,我想到的一种方法是使用使用证书打开的对称密钥。

所以一次性设置步骤是(理论上由 DBA 执行):

  1. 创建主密钥
  2. 将主密钥备份到文件、刻录到 CD 并异地存储。
  3. 打开主密钥并创建证书。
  4. 将证书备份到文件,刻录到 CD 并异地存储。
  5. 使用证书创建具有所选加密算法的对称密钥。

然后任何时候存储过程(或通过 Management Studio 的人类用户)需要访问加密数据,您必须首先打开对称密钥,执行任何 tsql 语句或批处理,然后关闭对称密钥。

那么就 asp.net 应用程序而言,在我的例子中是应用程序代码的数据访问层,数据加密是完全透明的。

所以我的问题是:

  1. 是否要打开、执行 tsql 语句/批处理,然后关闭存储过程中的所有对称密钥?我看到的危险是,如果 tsql 执行出现问题怎么办,并且代码 sproc 执行永远不会到达关闭密钥的语句。我认为这意味着密钥将保持打开状态,直到 sql 杀死 sproc 执行的 SPID。

  2. 我是否应该考虑对我需要执行的任何给定过程进行三个数据库调用(仅在需要加密时)?一次数据库调用打开密钥,第二次调用执行存储过程,第三次调用关闭密钥。 (每个调用都包含在自己的 try catch 循环中,以最大限度地提高打开密钥最终关闭的几率。)

  3. 我在使用客户端事务时需要注意什么(这意味着我的代码是客户端,并启动一个事务,执行多个存储过程,然后假设成功提交事务)?

【问题讨论】:

  • 感谢这个信息丰富的问题​​,我正在查看 2 以保护我的证书密码免受 dba 的侵害(在提取信息之前执行 sql 语句以在一个连接中从应用层打开密钥),你认为是个好习惯吗? (stackoverflow.com/questions/21213393/…)。谢谢

标签: asp.net sql-server-2005 encryption


【解决方案1】:

1) 考虑在 SQL 2005 中使用 TRY..CATCH。不幸的是,没有 FINALLY,因此您必须分别处理成功和错误情况。

2) 如果 (1) 处理清理,则不需要。

3) SQL Server 的客户端和服务器事务之间并没有真正的区别。 Connection.BeginTransaction() 或多或少在服务器上执行“BEGIN TRANSACTION”(System.Transactions/TransactionScope 也是如此,直到它被提升为分布式事务)。至于在事务中多次打开/关闭密钥的问题,我不知道有什么需要注意的问题。

【讨论】:

  • 我不打算使用 sql 2005 的 CLR 功能来实现存储过程,而是使用普通的 tsql。还是说 tsql 现在支持 try...catch?如果是这样,那就太好了!
  • 是的,SQL 2005 增加了对 T-SQL 的“异常”处理支持,但我没有链接到 MSDN :) 搜索 BEGIN TRY。
【解决方案2】:

我是选项 3 的忠实粉丝。

假装你要在任何地方设置交易基础设施:

  1. 如果现有事务尚未启动,则每当要调用数据存储时,就会创建一个。
  2. 如果事务已经到位,则调用数据存储挂钩到该事务。这对于保存/进入数据库事件引发的业务规则通常很有用。 IE。如果您有一条规则,即每当您出售一个小部件时,您都需要更新一个 WidgetAudit 表,那么您可能希望将小部件审计插入调用包装在与告诉数据存储小部件已售出的事务相同的事务中。
  3. 每当数据存储的原始调用者(从第 1 步开始)完成时,它都会提交/回滚事务,这会影响在其调用期间发生的所有数据库操作(使用 try/catch/finally)。

一旦创建了这种类型的交易,那么在开始时(交易打开时)添加打开的密钥并在结束时(就在交易结束之前)关闭密钥变得很简单。对数据存储进行“调用”并不像打开与数据库的连接一样昂贵。确实是像 SQLConnection.Open() 这样的东西会消耗资源(即使 ADO.NET 正在为您汇集它们)。

如果您想要这些类型代码的示例,我会考虑查看 NetTiers。它为我们刚刚描述的事务提供了一个非常优雅的解决方案(假设您还没有想到什么)。

只需 2 美分。祝你好运。

【讨论】:

  • 谢谢泰勒。我很感激反馈。但是,我不得不认为执行单个命令(带有打开键的sproc、各种sql语句和关闭键)会比执行三个命令执行得更好。
  • 另外,关于事务,我的偏好通常是将它们隔离到服务器端。我倾向于相信这会更好地扩展,尽管我无法证明这一说法。
【解决方案3】:
  1. 您可以使用@@error 查看在调用 SQL 中的存储过程期间是否发生任何错误。

  2. 不要复杂。

  3. 可以,但我更喜欢在 SQL Server 本身中使用事务。

【讨论】:

  • 关于#2,我有一个基本的“数据访问”类,它使打开和关闭加密密钥变得非常透明。所以我不太担心复杂性,更多的是额外的数据库流量,现在与数据库的每次交互都需要执行至少三个命令。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多