利用DPAPI技术,实现浏览器地址栏字符串的加密
前言:
DPAPI特别有用,因为它能够消除使用密码的应用程序所带来的密钥管理问题。虽然加密能确保数据安全,但您必须采取额外的步骤来确保密钥的安全。 DPAPI 使用与 DPAPI 函数的调用代码关联的用户帐户的密码,以便派生加密密钥。因此,是操作系统(而非应用程序)管理着密钥。
DPAPI能够与计算机存储或用户存储(需要一个已加载的用户配置文件)配合使用。DPAPI 默认情况下用于用户存储,但您可以通过将 CRYPTPROTECT_LOCAL_MACHINE 标志传递给 DPAPI 函数来指定使用计算机存储。
这种用户配置文件方式提供了一个额外的安全层,因为它限制了哪些用户能访问机密内容。只有加密该数据的用户才能解密该数据。但是,当通过 ASP.NET Web 应用程序使用 DPAPI 时,使用用户配置文件需要您执行额外的开发工作,因为您需要采取明确的步骤来加载和卸载用户配置文件(ASP.NET 不会自动加载用户配置文件)。
计算机存储方式更容易开发,因为它不需要管理用户配置文件。但是,除非使用一个附加的熵参数,否则并不安全,因为该计算机的任何用户都可以解密数据。(熵是一个设计用来使解密机密内容更为困难的随机值)。使用附加的熵参数出现的问题在于它必须由应用程序安全地存储起来,这带来了另一个密钥管理问题。
注意:
如果您将 DPAPI 和计算机存储一起使用,那么加密字符串仅适用于给定的计算机,因此您必须在每台计算机上生成加密数据。不要在场或群集中将加密数据从一台计算机复制到另一台计算机。
如果将 DPAPI 和用户存储一起使用,则可以用一个漫游的用户配置文件在任何一台计算机上解密数据。
DPAPI只在2k以上的系统上才有,win9x系列就不要想了.
________________________________________
以下利用DPAPI技术来加密查询字符串。
第一步:站点添加对System.Security.dll程序集的引用。
第二步:建立类,这里利用DPAPI和十六进制数结合的方式对数据进行加密。
HexEncoding.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Security.Cryptography;
/// <summary>
/// HexEncoding 的摘要说明
/// </summary>
public class HexEncoding
{
public HexEncoding()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
/// <summary>
/// 将十六进行字节数组转换成字符串
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static string GetString(byte[] data)
{
StringBuilder Results = new StringBuilder();
foreach (byte b in data)
{
Results.Append(b.ToString("X2"));
}
return Results.ToString();
}
/// <summary>
/// 将字符串转换为十六进行字节数组
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static byte[] GetBytes(string data)
{
byte[] Results = new byte[data.Length / 2];
for (int i = 0; i < data.Length; i += 2)
{
Results[i / 2] = Convert.ToByte(data.Substring(i, 2), 16);
}
return Results;
}
}
EncryptedQueryString.cs
using System;
using System.Text;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Security.Cryptography;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public class EncryptedQueryString :
System.Collections.Specialized.StringDictionary
{
public EncryptedQueryString()
{
// TODO: 在此处添加构造函数逻辑
}
/// <summary>
///
/// </summary>
/// <param name="encryptedData"></param>
public EncryptedQueryString(string encryptedData)
{
byte[] RawData = HexEncoding.GetBytes(encryptedData);
byte[] ClearRawData = ProtectedData.Unprotect(
RawData, null, DataProtectionScope.LocalMachine);
string StringData = Encoding.UTF8.GetString(ClearRawData);
int Index;
string[] SplittedData = StringData.Split(new char[] { '&' });
foreach (string SingleData in SplittedData)
{
Index = SingleData.IndexOf('=');
base.Add(
HttpUtility.UrlDecode(SingleData.Substring(0, Index)),
HttpUtility.UrlDecode(SingleData.Substring(Index + 1))
);
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public override string ToString()
{
StringBuilder Content = new StringBuilder();
foreach (string key in base.Keys)
{
Content.Append(HttpUtility.UrlEncode(key));
Content.Append("=");
Content.Append(HttpUtility.UrlEncode(base[key]));
Content.Append("&");
}
Content.Remove(Content.Length-1, 1);
byte[] EncryptedData = ProtectedData.Protect(
Encoding.UTF8.GetBytes(Content.ToString()),
null, DataProtectionScope.LocalMachine);
return HexEncoding.GetString(EncryptedData);
}
}
第三步:程序中使用类加密查询字符串
首先建立一个发送页面Send.aspx,代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Send.aspx.cs" Inherits="Send" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>发送页面</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="MyData:" Width="85px"></asp:Label>
<asp:TextBox ID="MyData" runat="server"></asp:TextBox><br />
<asp:Label ID="Label2" runat="server" Text="MyDataTwo:" Width="85px"></asp:Label>
<asp:TextBox ID="MyDataTwo" runat="server"></asp:TextBox><br />
<asp:Button ID="SendCommand" runat="server" OnClick="MyData_Click" Text="Send Info" /></div>
</form>
</body>
</html>
Send.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Send : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void MyData_Click(object sender, EventArgs e)
{
string strMyData = this.MyData.Text;
string strMyDataTwo = this.MyDataTwo.Text;
EncryptedQueryString QueryString = new EncryptedQueryString();
QueryString.Add("MyData", strMyData);
QueryString.Add("MyDataTwo", strMyDataTwo);
Response.Redirect("Receive.aspx?data="+QueryString.ToString());
}
}
再建立一个接收页面代码Receive.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Receive.aspx.cs" Inherits="Receive" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>接收页面</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Literal ID="litFlag" runat="server"></asp:Literal></div>
</form>
</body>
</html>
Receive.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class Receive : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string strMyData = "";
string strMyDataTwo = "";
EncryptedQueryString QueryString = new EncryptedQueryString(Request.QueryString["Data"]);
foreach (String key in QueryString.Keys)
{
strMyData = QueryString["MyData"].ToString();
strMyDataTwo = QueryString["MyDataTwo"].ToString();
}
this.litFlag.Text = "MyData:" + strMyData + "---->>>MyDataTwo:" + strMyDataTwo;
}
}
}
________________________________________
效果图如下:(注意看浏览器地址栏的变化,由于比较懒所以只在本地测试了。)
------>>>>
摘自 爱智旮旯