保护代码中的数据库连接字符串和其他敏感设置

原文参考:http://msdn.microsoft.com/zh-cn/library/aa686056.aspx#XSLTsection124121120120

SRC:http://www.obviex.com/samples/Encryption.aspx

             http://www.obviex.com/samples/EncryptionWithSalt.aspx

 

本文假定读者熟悉 C# 和 Visual Basic .NET

摘要

保护应用程序机密(如数据库连接字符串和密码)要求仔细考虑许多相关因素,如数据的敏感程度、可以获得访问权限的人以及如何在安全性、性能和可维护性之间获得平衡,等等。本文解释了数据保护的基础知识,并比较了几种可用于保护应用程序设置的技术。作者探讨了要避免的事项,如在源代码中隐藏密钥,以及使用“本地安全机构”。此外,他还提出了一些有效的解决方案,如数据保护 API。

本页内容

数据隐藏数据隐藏
限制对数据的访问限制对数据的访问
加密数据加密数据
权衡选择权衡选择
存储加密数据存储加密数据
单向和双向加密单向和双向加密
哈希算法哈希算法
加密密钥加密密钥
保护加密密钥保护加密密钥
了解本地安全机构了解本地安全机构
使用 DPAPI使用 DPAPI
在应用程序源代码中隐藏密钥在应用程序源代码中隐藏密钥
独立存储独立存储
小结小结

在开发人员新闻组和在线论坛上,经常讨论有关保护数据库连接字符串、密码和其他敏感应用程序设置的问题。尽管大多数专业安全人员都同意使用软件无法隐藏机密的看法,但仍然有某些已知技术可以为大多数类型的应用程序提供充足的保护。所有的现有数据保护方法都基于三种基本技术:隐藏、访问控制和加密。这些技术可以单独使用,也可以结合使用。不管您决定是选择一种现有技术、还是构建自己的数据保护机制来保护应用程序机密,您的基本选择都局限于这三种方法。

在本文中,我将探讨数据保护的基础知识,并比较几种能够帮助您更好地管理机密数据的技术。我将指出适合使用这些技术的情况,以及应该避免使用这些技术的情况。我还将提供可以帮助您实现数据保护机制的代码示例、工具和 API 的参考。

数据隐藏


数据隐藏有时称为隐藏式保全。如果依赖这种技术,您就假设了只有您知道敏感信息存储的地方,并希望其他人都无法找到这些信息。此处的忠告是,应用程序也必须知道如何访问数据,因此是否能够保证机密的安全将在很大程度上取决于应用程序保护这种知识的能力。

最常见的隐藏敏感应用程序设置的地方包括应用程序源代码、配置文件和 Windows? 注册表。数据也可以存储在诸如 IIS 元数据库、通用数据链接 (UDL) 文件、自定义文件之类的怪异位置。

简单地隐藏数据通常只能提供很少的(如果存在)安全性。大多数情况下,黑客非常容易发现您的机密。例如,通过监视正在运行的应用程序所执行的系统更改(请参见图 1),入侵者可能会发现数据的位置。这可以通过实用工具(如SysInternals 上的 regmon、fileman 和 diskmon)来实现。

MIissues0311protectyourdatafig01

图 1 Regmon

反编译 .NET 程序集的简单易行会导致更严重的威胁。使用诸如 AnakrinoSalamander 之类的反编译器,应用程序源代码可以进行反向工程,从而公开敏感数据或应用程序的逻辑(请参见图 2)。

MIissues0311protectyourdatafig02

图 2 反编译

限制对数据的访问


如果对数据的访问是受限制的,那么数据的位置就不需要保密。相反,这种技术依赖于构建在操作系统中的技术功能,该功能可以防止未经授权的实体访问数据。通常,访问限制是以调用方的标识或对公共机密的了解(请参见图 3)为基础的。访问控制列表 (ACL)、Microsoft 数据保护 API (DPAPI) 和独立存储就使用这种技术来保护数据。

MIissues0311protectyourdatafig03

图 3 访问控制

在正确使用时,受限制的访问是最有效的安全措施之一,但遗憾的是,这种技术有局限性。例如,对于以匿名用户或在不同的用户上下文中运行的应用程序来说,基于用户标识的访问控制作用不大。基于标识的访问控制的另一个问题是,不能防止在同一标识下运行的其他应用程序互相访问数据。图 4 列出了与基于标识的访问控制有关的常见问题。

另一方面,当访问控制基于对机密的了解时,保护该机密就成为一个问题。其他与受限制访问有关的困难取决于具体实现。例如,在大型企业环境中难以管理 ACL,并且受保护的存储区可能需要调用方具有管理特权,这就违反了最低权限规则。

加密数据


使用加密方法时,隐藏或控制对数据的访问都不是主要目的。由于信息被加密,因此对于未经授权的入侵者来说,知道信息的位置并且能够访问它并不一定能使该信息可用,除非他找到了解密密钥。

虽然加密是经过时间验证的数据保护技术,但它不能提供完美的解决方案,而仅仅是将保护数据的问题转化为保护加密密钥的问题。对于任何其他类型的敏感数据,都是使用相同的技术(隐藏和访问控制)来保护加密密钥。

选择或构建数据保护机制时,您应该针对潜在的威胁来衡量安全漏洞。如果根据已讨论过的基本数据保护技术来考虑您的解决方案,可能更容易对其进行评价。例如,如果存储的数据库连接信息在 UDL 文件中包含了用户的 SQL 凭据(请参见图 5),则您的数据安全性实质上取决于文件权限 (ACL),这是一种受限制的访问。(在某种程度上,这也取决于数据隐藏,但在这种特定情况下,数据隐藏是非常脆弱的安全措施,因为不需要花费太多精力就能找到 UDL 文件。)虽然 ACL 在数据保护中扮演着极为重要的角色,但如果黑客设法获得了对 UDL 文件的读取权限,那么您的 SQL 凭据就会被泄漏,理解这一点非常重要。

MIissues0311protectyourdatafig05

图 5 UDL 文件中的凭据

除非潜在威胁的级别很低或者数据不是很重要,否则应该避免只使用一种数据保护技术的解决方案。通常,解决方案使用的技术越多就越安全。

权衡选择


正如许多安全专家所述,保护机密的最佳方法就是根本不保存机密。例如,如果您希望保护包含 SQL 凭据的数据库连接字符串,那么应考虑不使用 SQL 身份验证。如果应用程序可以使用 Windows 身份验证(而不是 SQL 身份验证)来连接到数据库服务器,那么您根本不需要考虑保护 SQL 凭据。

遗憾的是,并不是总能避免存储敏感信息。如果确实需要存储机密数据,那么应该通过分析应用程序及其安全要求,来开始寻找正确的解决方案。下列问题有助于您决定哪个选项最适合您:

  • 您要保护的信息有多重要?当数据安全遭到破坏时,您预期能够承受哪种损失?

  • 您想保护数据以防止哪种用户访问?您要保护数据免受机会主义黑客(例如,喜欢访问不允许访问的信息、但却不是有意攻击系统的员工)的攻击吗?还是要保护数据免受恶意黑客(他们愿意花费时间、精力和金钱来破坏系统的安全)的攻击?您认为一个潜在黑客获得您的数据有多大困难?

  • 您的应用程序确实需要知道敏感数据的未加密文本吗?

  • 您希望保护数据库连接字符串,还是也希望管理其他类型的数据?

  • 访问您数据的应用程序使用多少标识?应用程序使用单一用户标识,还是使用多个用户标识?

  • 应用程序必须支持在哪些版本的操作系统上运行?

  • 应用程序的性能和安全性哪个更重要呢?您愿意牺牲性能以得到更安全的应用程序吗?

  • 负责定义数据的机制是什么?这是通过手动(例如,使用文本编辑器)完成,还是通过编程方式完成?如果数据是通过编程方式创建的,那么是按照使用这些设置的应用程序还是由其他应用程序来定义应用程序的设置?

  • 在您的组织或公司内部有多少应用程序使用数据保护?如果应用程序不止一个,那么它们的要求都相同吗?您是希望重复使用能满足所有应用程序要求的单一解决方案,还是对每个应用程序都使用不同的数据保护机制?

  • 部署您的应用程序时,对于支持人员来说,管理其安全性有多困难?为您的应用程序提供支持的小组接受您的解决方案吗?

根据这些问题的答案,您可能希望选择一个最佳方法。在本文后面,我将分析几种数据保护技术,这些技术可用于最普通的应用程序,但首先我将概述一些在任何情况下都应该避免的事项。

以纯文本形式存储敏感数据的所有方法都被认为是不安全的,因为它们会将数据公开给设法取得数据源读取权限(要做到这一点可能比您想的还要容易)的任何人。您应该避免将未加密的数据保存在 Windows 注册表、配置文件、COM+ 目录、独立存储区、自定义文件、IIS 元数据库以及 UDL 文件中。此外,绝对不要以纯文本形式存储敏感数据。

绝对的安全可能永远也达不到,但是足够的安全无疑可以实现。一些应用程序的安全性要求需要复杂且非传统的解决方案,特别是对于银行、军事机密、执法记录以及科学研究等领域。但是,绝大多数解决方案都包含以下三个步骤:加密数据,使用 ACL 限制对加密数据的访问,以及隐藏并限制对加密密钥的访问。

在实现数据保护时,您可能要考虑其他安全方面,如数据篡改,但是由于数据篡改不影响保密性,所以本文将不探讨这个问题。相反,我将介绍有关将加密数据存储到什么地方、使用哪种类型的加密和加密算法以及如何保护加密密钥等更实际的问题。

存储加密数据


除非您有更好的理由采取其他手段,否则请将加密数据存储在应用程序的配置文件或 Windows 注册表中。使用这两个选项的主要好处在于,不仅具有使用 ACL 保护数据的能力,而且还便于通过编程方式进行访问。任何其他类型的数据存储可能至少缺少其中一个优点,虽然可能会添加其他优势,但这不可能弥补额外的实施工作。

虽然一些开发人员坚持,基于 Microsoft .NET Framework 的应用程序不应该使用注册表,但事实并非如此。注册表的主要缺点在于,它不太适合 XCOPY 部署方案,但是由于目前许多应用程序通过安装程序进行部署,并要求在安装它们的系统上执行特定配置步骤,因此对 XCOPY 的支持可能不是必需的。注册表的另一个缺点在于,它特定于 Windows 平台,而且可能不支持其他操作系统。只有当非 Windows 平台开始支持公共语言实现 (CLI) 时,该限制才会成为主要问题。

如果您关心 XCOPY 部署或者与非 Windows 平台的互操作性,请使用配置文件;否则,请选择最适合您需要的选项。如果您必须存储由多个应用程序共享的设置,或者以编程方式定义这些设置,则可能会发现管理注册表要容易得多。不借助编程方式更改的应用程序特定的设置可以存储在配置文件中。在以上两种情况下,都不要忘记将合适的 ACL 应用到数据存储区。例如,为运行应用程序的用户帐户分配对保存敏感数据的文件或注册表项的读取权限,是个不错的主意。类似,应该将写入权限显式指定给允许修改数据的用户或用户组(如 Administrators)。拒绝任何其他人的访问权限。

单向和双向加密


加密数据的方法有两种:单向(通常称为哈希算法)和双向。从技术上讲,哈希算法不是加密算法,但是因为这两种技术都可以用类似的方式(即,将纯文本数据转化为密文)进行数据保护,所以我把它们看作是逻辑上的对应方法。

尽管哈希算法还有其他用途,但在数据保护领域中,它比双向加密具有更大的优势。首先,哈希算法更容易使用。其次,因为哈希算法不使用加密密钥,这样就消除了密钥管理问题,本文稍后会讨论这个问题。哈希算法的主要缺点是它不支持解密,但是在某些情况下,这个问题反倒是塞翁失马。

基于密码的身份验证是哈希算法优于双向加密的典型例子。如果您的应用程序仅为了身份验证目的而保存密码,请不要使用对称密钥或公钥对其进行加密,而是存储其哈希值。当用户登录时,应用程序不会解密和比较纯文本密码,而是比较密码哈希值。要降低词典攻击的风险,请始终使用带有哈希值的 salt 值。 salt 值是随机数据,它是在纯文本被哈希处理并与哈希值一起存储之前,追加到纯文本的,这样以后就可以用于其他纯文本值与哈希值的比较。要查看将 salt 处理的哈希值用于基于密码的身份验证的示例,请查看 2003 年 8 月号的MSDN? Magazine 中的 Security Briefs 专栏。

哈希算法


MD5 和 SHA-1 是最常用的哈希算法。SHA-1 哈希值有 160 位长,而 MD5 哈希值有 128 位长。SHA-1 算法比 MD5 慢,但更安全。除了 MD5 和 SHA-1,.NET Framework 还提供对 256 位、384 位和 512 位版本的 SHA 算法的支持,虽然这些算法可能更慢,但它们更安全。

对数据进行哈希处理的最简单方法是调用 FormsAuthentication 类的 HashPasswordForStoringInConfigFile 方法,如下面的示例所示:

using System.Web.Security;
string base64HashValue = 
    FormsAuthentication.HashPasswordForStoringInConfigFile
        ("mypassword", "sha1");

遗憾的是,该方法只支持 MD5 和 SHA-1 哈希算法,因此如果您想使用 SHA-256、SHA-384 或 SHA-512 哈希值,将需要编写更多代码。如何:Hash Data with Salt 中的示例解释了如何使用不同的哈希算法来生成和比较哈希值。

加密密钥


如果您的应用程序需要知道敏感数据的文本值,就不能使用哈希算法。这种情况下,应使用利用对称密钥或公钥/私钥的双向加密。如果您不确定要选择哪种类型的加密密钥,请使用对称密钥。公钥加密的主要缺点是性能低,其性能比对称密钥加密低 1000 倍。公钥加密还对基于文本的可加密数据的大小施加某些限制。尽管公钥加密可用于数据保护,但实际上使用公钥所做的事都可以在其他技术的协助下实现。因为公钥最适于安全密钥交换和数字数据签名,在这里我将忽略它们,而集中讨论对称密钥加密。

在选择加密算法时,选择带有尽可能长的密钥的最安全算法是非常有意义的。在 .NET Framework 所支持的所有对称密钥算法中,美国政府认可的 Rijndael 算法(也称为高级加密标准,即 AES 算法)被认为是最安全的。该算法支持 128、192 以及 256 位密钥。有关 Rijndael 的详细信息,请参阅 James McCaffrey 有关该问题的文章“Encrypt It:Keep Your Data Secure With the New Advanced Encryption Standard”。

与 .NET Framework 所支持的其他对称密钥算法相比,Rijndael 算法还有一个优点。其他算法都是以现有 CryptoAPI 模块的 .NET Framework 瘦包装类的形式提供,而 Rijndael(实现为 RijndaelManaged 类)是完全以托管代码编写的。请注意,有些开发人员认为这是个缺点,并宁愿使用 Rijndael 算法的非托管实现来获得更好的性能。

遗憾的是,Rijndael 算法的这一实现只在 Windows XP 或更高版本上得到支持,而且系统还必须安装有 .NET Framework。如果您的应用程序需要与运行在 Windows 2000 或更早版本上的非托管应用程序兼容,请使用三重 DES,它是安全性较低的 DES 算法的一个比较好的版本。三重 DES 算法支持 112 和 168 位密钥,虽然建议使用 168 位密钥。因为对密钥的奇偶校验位的处理方式不一致,168 位的三重 DES 密钥有时称为 192 位密钥。如果您希望允许托管和非托管应用程序使用相同的三重 DES 密钥加密或解密数据,应注意派生密钥的通行码(密码)应该只包含可打印的 ASCII 字符;否则,生成的密钥将不匹配(这是由于三重 DES 算法的 .NET 实现的限制)。

通常,人们认为原始的 DES、RC2 和 RC4 算法的安全性比 Rijndael 和三重 DES 低,因此应该避免使用它们。在任何情况下,都不应该使用自己编写的加密算法。永远不要认为,如果您是代码的原作者,就没有人能够破解它。

MIissues0311protectyourdatafig06

图 6 数据加密方案

图 6 说明了您可以使用的各种数据加密方案。

保护加密密钥


使用对称密钥加密和解密应用程序数据时,自始至终都可以生成相同的密钥很重要。这就带来了保护密钥或密钥生成逻辑(不要与加密算法混淆)的问题。虽然有几种技术可以用于完成该任务,但是它们都有缺陷。让我们分析一下最适合的可用选项及方案。

有两种方法可以生成持久对称密钥:自己定义密钥,或者让操作系统定义。选择第一个选项时,您可以将实际的密钥字节硬编码到应用程序源代码中,或者实现一致的逻辑以从某些不变的特征派生出密钥。这些特征通常包含一个通行码(密钥就是从该通行码派生出来的),而且还可能包含其他值(如初始化向量)。不论是将密钥字节硬编码还是实现密钥生成逻辑,您都必须将密钥隐藏在应用程序源代码中。该选项赋予您更多的控制权和灵活性,但是如果对应用程序的源代码进行反向工程,也会给您的数据带来更大的风险。另外,您可以将密钥存储在一个持久位置(如文件或注册表),并通过 ACL 保护该位置。但是,因为该方法容易导致维护错误,所以建议不要这样做。

更安全但具有更多限制的方法就是让操作系统生成密钥。使用诸如本地安全机构 (LSA) 或 DPAPI 这样的操作系统功能可以做到这一点。

了解本地安全机构


在 Windows NT 4.0 的鼎盛时期,LSA 策略函数 LsaStorePrivateData 和 LsaRetrievePrivateData 提供了保护应用程序机密的合理安全方法。虽然 LSA 策略函数在 Windows 2000 及更高版本上都可用(并且仍然用于保护诸如为 Windows 服务定义的密码之类的设置),但 Microsoft 建议不要使用它们,因此出于完整性考虑,我只提及这些函数并解释为什么应该避免使用它们。

LSA 策略函数的一个问题是,与密钥管理和加密算法一起使用 Windows 注册表的受保护区域来处理数据存储。这看起来是件好事,但实际不然,因为 LSA 策略函数可用的存储量被限制为 4096 槽,而且其中的一半已被系统占用。如果应用程序继续使用 LSA 策略来存储敏感数据,那么将存在空间不足的危险。其次,由于只有高级特权用户能够调用 LSA 策略函数,因此对于在非特权帐户下运行的应用程序(如 ASP.NET),LSA 策略函数将不起作用。更糟糕的是,还存在诸如LSADUMP2 这样可以泄漏 LSA 机密的工具。底线:不要将 LSA 策略函数用于数据保护。

使用 DPAPI


作为 LSA 策略函数的备选方案,Microsoft 建议使用名为 DPAPI 的 CryptoAPI 的子集。DPAPI 包括两个可以用于数据保护的函数:CryptProtectData 和 CryptUnprotectData。这些函数在 crypt32.dll 中实现,并且可以通过 P/Invoke 从基于 .NET Framework 的应用程序调用。DPAPI 是操作系统的一部分,可以在 Windows 2000 及更高版本上使用。

与 LSA 函数不同,DPAPI 不处理数据存储,但是它可以生成计算机特定或用户特定的密钥,以加密和解密数据。为了区分这两种类型的密钥,DPAPI 文档将它们称为计算机存储和用户存储。

计算机特定密钥通常不太安全,因为任何取得系统访问权限的人都可以使用它们。通过将密码(也称为次级熵)传递到 DPAPI 函数,可以生成一个更安全版本的计算机特定密钥。该选项更好,因为它需要调用方知道该密码的值,但却带来了存储密码的问题,这就又回到了最初的问题。计算机特定密钥的另一个问题是,当环境发生改变时,不能保证它们与原来的密钥相同。诸如将应用程序移到其他计算机上或重新建立系统之类的更改,可能会导致使用带有计算机特定密钥的 DPAPI 的应用程序出现崩溃。

虽然用户特定密钥被认为更加安全,但是它们具有其他任何基于标识的访问控制所具有的局限。首先,因为用户密钥只能由运行已加载用户配置文件的程序生成,它们不能与 ASP.NET 应用程序和某些内置帐户运行的应用程序一起使用。有一种方法可以通过使用服务组件来克服这种局限,但是必须付出的代价是提高复杂程度以及降低应用程序性能。它还需要在特权帐户下运行服务组件,这就违反了最低权限原则。如果您决定使用带有用户特定密钥的 DPAPI,则必须知道只有加密数据的用户才能解密结果。显而易见,这不能用于可以在其他用户帐户下运行或其设置可以由其他用户定义的应用程序。用户特定密钥的另一个问题是,它们允许运行在同一用户配置文件下的所有应用程序互相访问数据,这是一个潜在的安全隐患。对于使用计算机存储的 DPAPI,该问题可以通过要求调用方提供次级熵来解决,但就像在前面的示例中一样,这会带来存储该熵的问题。遗憾的是,DPAPI 不允许您同时(在同一 CryptProtectData 调用上)使用计算机特定和用户特定的密钥。

对于在带有已加载用户配置文件的单个用户帐户下运行并由同一用户定义其设置的应用程序,建议使用 DPAPI。(有关详细信息,请参阅提要栏“The Loaded User Profile。”)运行在本地或域用户帐户下的 Windows 服务应用程序就是一个典型示例。如果您的应用程序满足这些要求,就应该使用带有用户特定密钥的 DPAPI。对于其他应用程序,您可以使用由次级熵保护并带有计算机特定密钥的 DPAPI(请参阅“Use DPAPI (Machine Store) from ASP.NET”或Use DPAPI to Encrypt and Decrypt Data 中的示例)。您可以在应用程序源代码中定义该熵,并模糊处理应用程序二进制代码,以便该熵难以被他人找到。然而,如果您选择这种方法,则应该意识到,即使是模糊处理的代码可以进行反向工程。要确定您可以使用或不可以使用的模糊处理方法,请阅读 Brent Rector 撰写的有关该问题的文章“The Premier Obfuscator for Microsoft .NET Applications!”,以及 Gabriel Torok 和 Bill Leach 撰写的“Obfuscate It:Thwart Reverse Engineering Attempts on Your Visual Basic .NET or C# Code”。

如果您的应用程序无法直接使用带有用户特定密钥的 DPAPI,并且不能承受反向工程的风险,那么应考虑使用服务组件来实现 DPAPI,但要意识到该选项将影响应用程序的性能。(请参阅“Use DPAPI (User Store) from ASP.NET with Enterprise Services”)。如果您选择该选项,请准备实现授权方案,以防止恶意的应用程序和用户调用服务组件,这可能不是一项简单的任务。要了解如何解决该问题,请参见CipherSafe.NET 工具及其附带的文档;该应用程序阐释了如何将 DPAPI 用于敏感应用程序管理,并提供了一个解决授权问题的有趣方法。

在应用程序源代码中隐藏密钥


尽管专业安全人员不断催促应用程序开发人员停止在他们的应用程序源代码中“隐藏”加密密钥(和其他敏感数据),但是应用程序开发人员仍然置之不理。对这种矛盾的解释可以一分为二。开发人员选择这种方法的一个明显无需解释的原因是,该方法非常易于实现。另一个解释是,备选的选项在某些情况下可能不起作用。例如,请考虑以下情况:运行在不同计算机上的几个应用程序(比如说 Windows 服务)必须使用相同的密钥来加密和解密存储在数据库中的数据。在这种情况下,使用 DPAPI 来加密是不可行的,因此开发人员可能选择将密钥嵌入到应用程序源代码中。这样容易实现,但不安全。更好的方法是,要求管理员在应用程序安装时定义加密密钥,使用带有运行应用程序帐户的用户特定密钥的 DPAPI 加密其值,然后将加密后的值保存在 Windows 注册表或应用程序配置文件中。要知道,虽然该方法是一个更安全的技术实现,但却带来了过程上的问题。

将密钥嵌入应用程序源代码作为唯一选项的另一种情况是,应用程序数据的所有者对宿主应用程序的计算机具有受限制的访问权限或根本没有访问权限。宿主环境的 Web 就是一个明显的示例。如果将密钥嵌入应用程序源代码是您的唯一选择,那么必须意识到相关的风险并进行相应地处理。

在这种情况下,主要风险来自反向工程,此时只能通过模糊处理来解决。虽然模糊处理不能禁止反向工程,但是它可以使该过程的成本提高并且更费时。比较图 7(它显示了由Demeanor 进行模糊处理的反编译过的程序集)和图 3。因为经过模糊处理的程序集中的所有非公共符号都是用不可打印的字符重新命名的,并且这些字符串都经过了加密,所以从程序集重建应用程序逻辑几乎是不可能的。商用反编译器(如Salamander)通过将不可打印的字符转换为可打印的等效值,然后将应用程序类转换为源文件,从而简化了反向工程的工作,但是这不仅花费金钱,而且还需要黑客理解不可读的符号(此时,spaghetti 代码就可以实际派上用场了!)。

MIissues0311protectyourdatafig07

图 7 反编译经过模糊处理的程序集

如果您在应用程序中定义密钥,那么除了将程序集模糊处理以外,请不要试图在源代码中存储实际的密钥字节。相反,应使用持久的特征来实现密钥生成逻辑,如加密算法、密钥大小、通行码、初始化向量以及 salt(请参阅Encrypt and Decrypt Data Using a Symmetric (Rijndael) Key 中的示例)。这将引入一个附加的间接层,这样就不能通过简单地将符号从应用程序二进制代码中转储出来以得到密钥。只要不更改密钥生成逻辑和密钥特征,生成的密钥保证是相同的。不将静态字符串作为密钥生成特征可能也是个不错的想法,但还是稍逊于即时构建它们。还有一个建议是,用对待数据存储的方式来对待程序集,也就是应用合适的 ACL。只有当其他数据保护技术都不起作用,并且唯一的备选方法是不加密敏感数据时,才可以将该选项作为最后的解决办法。

独立存储


独立存储有时被认为是保护数据的方法。它可让您限制对应用程序程序集的数据访问。虽然该选项能有些帮助,但是由于独立存储不使用加密,因此不建议使用它来保护敏感数据;它更适于存储用户特定的应用程序设置。要存储用户特定的敏感应用程序数据,请将 DPAPI 和独立存储结合使用。

小结


对于保护敏感应用程序数据来说,没有完美的解决方案。现有的软件技术都不能保证绝对的安全。我们的目标是,在那些对应用程序有效并符合安全要求的方案中挑选出最好的、或者“危害最小”的选项。理解各种技术和技巧如何提供数据保护,将有助于您评估安全漏洞并防止您错误地产生安全感。

无论您是决定构建还是购买数据保护解决方案,请确保它使用强加密算法、为加密密钥提供合理的保护,以及限制对加密数据的访问。尽管没有软件解决方案可以保证应用程序数据的绝对安全,但是正确的方法可以帮助您避免最常见的安全隐患类型。

相关文章,请参阅:
Data Access Security
Security:Protect Private Data with the Cryptography Namespaces of the .NET Framework
Windows Data Protection
有关背景信息,请参阅:
Create an Encryption Library
Store an Encrypted Connection String in the Registry
Writing Secure Code

Alek Davis 是位于加拿大福尔松的 Intel Corporation 安全工程小组的高级开发人员。他具有针对解决企业应用程序安全性的 Windows 程序的丰富开发经验。Alek 拥有加利福尼亚州立大学 Sacramento 分校的计算机科学学士学位和软件工程硕士学位。

转到原英文页面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值