在这个快节奏的生活里,我们要求各种操作都要快捷方便!登录某些论坛或者购物网站的时候,即便您再喜欢某一个帖子或者某一件商品。但是如果登录的步骤过于繁琐,可能就会打消我们的热情。所以,现在网站都可以在一段时间内保存您的登录名和密码,让您在需要下次访问的时候,可以减少登录的繁琐步骤。这个就需要使用到Cookie加密技术!
用Cookie或者Session来保存登录信息已经是一种比较成熟的技术。但是对于账户信息如果把明文放在Cookie里面显然是非常危险的。Cookie 是以key-value的形式存数据。对于账户信息而言最简单的是 UserName 和 Password。如果以明文的形式放到Cookie 比如:UserName=fakeUser Password=fakePsd考虑到安全性的问题,显然没有任何website会这样做。那么是否可以把这几个字段都加密呢?
对 Key 的加密
对key字段像UserName, Password只需要在Server端加密并保存即可,甚至都无需还原成明文。
public static string MD5Hash(string input)
{
byte[ ] data = Encoding.UTF8.GetBytes(input.Trim( ).ToLowerInvariant( ));
using (var md5 = new MD5CryptoServiceProvider( ))
{ data = md5.ComputeHash(data); }
var ret = new StringBuilder( );
foreach (byte b in data)
{ ret.Append(b.ToString("x2").ToLowerInvariant( ));}
return ret.ToString( );
}
例如计算出UserName 和 Password的 MD5 hash 值,Cookie形式就可以表示成
ee11cbb19052e40b07aac0ca060c23ee=fakeUser
5f4dcc3b5aa765d61d8327deb882cf99=fakePsd
相比没有加密前安全性是不是高了那么一点点,但这肯定还是不够。我们最终的目标是对所有字段加密。
对Value的加密
对value字段加密就不能是单向的,试想一下如果在Server端对用户名加密放到Cookie再传到Client端, 看起来OK. 当Client端的cookie再传回Server端时,如果不能解密Encode后的用户名那么Cookie就等于失效了。
一个非常简单的算法就是用过异或来实现加密解密,比如提供一个秘钥 X,
encode_data = data ^ X
decode_data = encode_data ^ X
则 data == decode_data.
目前 .NET 提供不了不少对称加密算法都直接以dll 的形式给出了。.NET 中提供的对称加密算法都继承基类SymmetricAlgorithm
具体代码可以直接调用他们的子类像
TripleDESCryptoServiceProvider
RijndaelManaged
MSDN 上已经提供了的代码案例,这里就不再给出Test Sample,为了能够灵活的运用到项目中本人就封装了一些接口。
// 定义加密解密的接口
public interface IEncryptionProvider
{
byte[ ] Key { get; }
byte [ ] IV { get; }
Encoding Encoding { get; }
string Encrypt(string data);
string Decrypt(string encodeData);
}
//加密解密抽象基类
public abstract class BaseEncryptionProvider : IEncryptionProvider
{
protected byte[ ] _keyBytes;
protected byte [ ] _IVBytes;
public byte[ ] Key
{
get { if (this._keyBytes == null)
{ this.GenerateKeyIV(); }
return this._keyBytes;
}
}
//异或加密算法类
public class EOREncryptionProvider : BaseEncryptionProvider
{
private string _key;
public EOREncryptionProvider(string key)
{
if (string.IsNullOrEmpty(key))
{throw new ArgumentNullException("key");}
this._key = key;
}
public override void GenerateKeyIV()
{ this._keyLength - 1];} }
return dataBytes;
}
protected override byte[ ]
DecryptImpl(byte[ ] dataBytes)
{
int dataLength = dataBytes.Length;
int IVLength = this.IV.Length;
for (var i = 0; i < dataLength; i++)
{ if (i < IVLength)
{ dataBytes[i] ^= this.IV[i]; }
else { dataBytes[i] ^= this.IV[IVLength - 1]; }
}
return dataBytes;}
}
// .Net 内置加密算法的封装 public class SymmetricAlgoEncryptionProvider : BaseEncryptionProvider { private SymmetricAlgorithm _symmetricAlgorithm; public SymmetricAlgoEncryptionProvider(SymmetricAlgorithm providerImpl) { if (providerImpl == null) { throw new ArgumentNullException("providerImpl"); } this._symmetricAlgorithm = providerImpl; this._symmetricAlgorithm.Padding = PaddingMode.ISO10126; } protected override byte[] EncryptImpl(byte[] bytes) { byte[ ] encryptedData; using (var input = new MemoryStream(bytes)) using (var output = new MemoryStream()) { var encryptor = this._symmetricAlgorithm.CreateEncryptor(this.Key, this.IV); using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write)) { var buffer = new byte[1024]; var read = input.Read(buffer, 0, buffer.Length); while (read > 0) { cryptStream.Write(buffer, 0, read); read = input.Read(buffer, 0, buffer.Length); } cryptStream.FlushFinalBlock(); encryptedData = output.ToArray(); } } return encryptedData; } protected override byte[ ] DecryptImpl(byte[ ] bytes) { byte[] result; using (var input = new MemoryStream(bytes)) using (var output = new MemoryStream()) { var decryptor = this._symmetricAlgorithm.CreateDecryptor(this.Key, this.IV); using (var cryptStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read)) { var buffer = new byte[1024]; var read = cryptStream.Read(buffer, 0, buffer.Length); while (read > 0) { output.Write(buffer, 0, read); read = cryptStream.Read(buffer, 0, buffer.Length); } cryptStream.Flush(); result = output.ToArray(); } } return result; } public override void GenerateKeyIV() { this._symmetricAlgorithm.GenerateKey(); this._symmetricAlgorithm.GenerateIV(); this._keyBytes = this._symmetricAlgorithm.Key; this._IVBytes = this._symmetricAlgorithm.IV; } } 最后可以这样调用
static void Main(string[] args) { IEncryptionProvider provider = new EOREncryptionProvider("this is the key"); string data = "fakeUser"; string encodeData = provider.Encrypt(data); Console.WriteLine("encodeData:{0}", encodeData); string decodeData = provider.Decrypt(encodeData); Console.WriteLine("decodeData:{0}", decodeData); provider = new SymmetricAlgoEncryptionProvider(new TripleDESCryptoServiceProvider()); encodeData = provider.Encrypt(data); Console.WriteLine("encodeData:{0}", encodeData); decodeData = provider.Decrypt(encodeData); Console.WriteLine("decodeData:{0}", decodeData); } 最后Cookie形式就可以表示成 ee11cbb19052e40b07aac0ca060c23ee=EgkCFnUaFlI 5f4dcc3b5aa765d61d8327deb882cf99=vDwCZGvezDfudh91hRsiow