除了可以利用.NET Framework进行信息保护外,利用操作系统自身的API也可以保护用户关键数据。需要说明的是,DPAPI(Data Protection API)数据保护API技术分为托管和非托管两类,下面将分别介绍它们的实现机理。
托管型的Windows API利用系统组件处理加解密数据。下面将结合图3-1讲解WindowsAPI的运行原理和技术特点,帮助读者理解Windows API的重要作用,以及它和哈希数据处理的区别。
在图4-1中,Windows API执行数据加密事件的顺序分为6个步骤:
(1)从Windows服务控制管理器启动Win32®服务,并自动加载与运行该服务的账户关联的用户配置文件,允许Windows账户用于运行企业服务应用程序。
(2)Win32服务调用服务组件的一个启动方法,该方法可启动企业服务应用程序并加载服务组件。
(3)Web应用程序从Web.config文件中检索加密字符串。
(4)Web应用程序调用服务组件上的方法来解密连接字符串。
(5)服务组件与使用P/Invoke的DPAPI进行交互,调用Win32 DPAPI函数。
(6)解密的字符串返回Web应用程序。
需要注意的是,DPAPI要求使用Windows账户密码以派生加密密钥。DPAPI使用的账户是从当前的线程令牌(如果调用DPAPI的线程当前正在进行模拟)或进程令牌获取。
若要将DPAPI和用户存储结合使用,则加载与该账户关联的用户配置文件。如果将ASP.NET应用程序配置为模拟其调用方,ASP.NET应用程序线程会有一个关联的线程模拟令牌。与该模拟令牌关联的登录会话作为网络登录会话(在服务器上用来表示调用方)。网络登录会话不会导致加载用户配置文件,并且无法从密码中派生加密密钥,因为服务器没有被模拟的用户的密码(除非应用程序使用基本身份验证)。
为了消除这些限制,可以使用企业服务器应用程序中的服务组件(具有固定的进程标识),通过使用DPAPI提供加密和解密服务。Windows服务和服务组件一般配置为使用具有最少权限的相同账户运行,因此,服务组件可以访问加载的用户配置文件,同时也可以调用DPAPI函数以加密和解密数据。
图4-1 加密流程
如果没有从Windows服务中启动服务组件(并且该服务与之没有关联性),系统就不会自动加载用户配置文件。虽然可以调用某个Win32 API以加载用户配置文件(LoadUserProfile),但是要求调用代码是Administrators组的一部分,这会违反使用最少权限运行的原则。
每当调用服务组件的Encrypt和Decrypt方法时,Windows服务必须运行。在停止Windows服务时,就会自动卸载配置的配置文件,服务组件中的DPAPI方法也停止工作。
下面将通过实例具体讲解如何利用DPAPI托管代码类库加解密安全数据。此实例封装了对Win32 DPAPI函数的调用。要调用托管DPAPI类库,需要首先添加名称为DataProtection.dll的程序集,在代码中添加下列using语句:
实现加密方法需要实例化加密对象DataProtector,调用它的加密方法Encrypt,该方法只需要直接传入需加密的字符串即可。
Encrypt方法代码如下:
实现解密方法需要实例化加解密对象DataProtector,并且调用解密方法Decrypt把传入的数据进行解密。
Decrypt方法代码如下:
在Web系统研发时,很多开发人员习惯在Web.Config中用明文配置数据库连接串。这种做法异常的危险,一旦被黑客获取该连接串,服务器数据库的安全也就无法保证了。下面的实例说明如何加密和解密数据库连接信息,首先,打开VS2005以上版本的开发工具,创建一个名为DPAPIWeb的应用程序项目。
完成创建后,添加名称为System.EnterpriseServices的程序集引用。在设计模式下打开页面WebForm1.aspx,然后创建如图4-2所示的窗体。该页面使用的控件包括文本框控件TextBox和加解密按钮。
图4-2 加密流程
该实例的加密按钮需要调用DataProtectorComp服务组件对通过Web窗体输入的数据进行加密。加密后的数据显示在输入框中,具体代码如下:
解密按钮调用DataProtectorComp服务组件对txtEncryptedData字段内包含的前面已加密的数据进行解密,单击按钮事件的代码如下:
单击Build Solution按钮后对该实例进行编译。通过运行页面WebForm1.aspx将文本字符串输入到Data to Encrypt字段,然后单击Encrypt按钮加密。该操作将对COM+应用程序中的DataProtector服务组件进行调用,数据加密完成后在Encrypted Data字段中显示。如果单击Decrypt按钮,则原始文本字符串在Decrypted Data字段中显示。
如果要加解密Web.config配置文件中的数据库连接节,则需要修改解密代码。编辑解密单击按钮事件btnDecryptConfig_Click,并从Web.config 文件的<appSettings>读取数据库连接字符串。
单击事件代码如下:
完成上述工作后,读者可以尝试在Data to Encrypt字段中输入一个如下所示的数据库连接字符串:
单击加密Encrypt按钮,把显示的加密数据复制下来,复制到配置文件Web.config的设置节<appSettings>。
XML代码如下:
单击“解密”按钮,发现数据库连接字符串已成功地从Web.config文件读取出来,解密的连接字符串也已经成功地显示在Decrypted data 字段中。
非托管代码类提供对Microsoft Windows XP和更高版本操作系统中可用的DPAPI的访问,因为操作系统提供的服务不需要额外的库。它提供了一种使用用户或计算机凭据保护数据或取消保护数据的方法。
该类由两个用于非托管DPAPI的包装组成:Protect和Unprotect,这两个方法可用于对密码、密钥、连接字符串这类数据进行保护或取消保护。
下面的实例将为读者讲解如何利用非托管代码的类创建加解密的操作。加密时调用对象ProtectedData的加密方法Protect,通过数组的方法加密数据。解密时调用对象ProtectedData的解密方法Unprotect,通过数组的方法解密数据。
实例代码如下: