频道栏目
首页 > 资讯 > 加密解密 > 正文

保存登录信息的Cookie加密技术

16-04-25        来源:[db:作者]  
收藏   我要投稿

 所有需要账户登录的website 基本都会想到这样一个问题, 如何保持用户在一定时间内登录有效。

最近本人就在项目中遇到这样的需求,某些页面只能Admin账户登录后访问, 当登录Admin账户后如何才能保持登录信息呢?

用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 byte[] IV        {            get            {                if (this._IVBytes == null)                {                    this.GenerateKeyIV();                }                return this._IVBytes;            }        }        private Encoding _encoding;        public Encoding Encoding        {            get { return this._encoding ?? Encoding.UTF8; }            set { this._encoding = value; }        }        public string Encrypt(string data)        {             if (string.IsNullOrEmpty(data))             {                 throw new ArgumentNullException("data");             }            byte[] bytes = this.Encoding.GetBytes(data);            var encodedBytes = this.EncryptImpl(bytes);            return this.PostEncrypt(encodedBytes);        }        public string Decrypt(string encodeData)        {            if (string.IsNullOrEmpty(encodeData))            {                throw new ArgumentNullException("encodeData");            }            var bytes = this.PreDecrypt(encodeData);            var decodeBytes = this.DecryptImpl(bytes);            return this.Encoding.GetString(decodeBytes);        }        //加密算法的实现函数         protected abstract byte[] EncryptImpl(byte[] bytes);        //解密算法的实现函数         protected abstract byte[] DecryptImpl(byte[] bytes);        public virtual string PostEncrypt(byte[] bytes)        {            return System.Convert.ToBase64String(bytes);        }        public virtual byte[] PreDecrypt(string input)        {            return System.Convert.FromBase64String(input);        }        public abstract void GenerateKeyIV();    }

 

    //异或加密算法类        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._keyBytes = this.Encoding.GetBytes(this._key);            this._IVBytes = this.Encoding.GetBytes(this._key);        }        //考虑到秘钥长度以及数据长度等因素 具体实现算法多种多样         protected override byte[] EncryptImpl(byte[] dataBytes)        {            int dataLength = dataBytes.Length;            int keyLength = this.Key.Length;            for (var i = 0; i < dataLength; i++)            {                if (i < keyLength)                {                    dataBytes[i] ^= this.Key[i];                }                else                {                    dataBytes[i] ^= this.Key[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

 

相关TAG标签
上一篇:记一次sql server数据库手工注入
下一篇:科技改变生活:脑电波控制无人机飞行已成为现实-脑电波,意念,无人机
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站