首页 > 编程 > .NET > 正文

用ASP.NET加密Cookie数据

2024-07-10 12:57:12
字体:
来源:转载
供稿:网友
cookie确实在web应用方面为访问者和编程者都提供了方便,然而从安全方面考虑是有问题的,首先,cookie数据包含在http请求和响应的包头里透明地传递,也就是说聪明的人是能清清楚楚看到这些数据的。其次,cookie数据以cookie文件格式存储在浏览者计算机的cache目录里,其中就包含有关网页、密码和其他用户行为的信息,那么只要进入硬盘就能打开cookie文件。图1是一个cookie文件的内容:

如果你未曾留意你的机器里有cookie文件,可以按下列方法查看:打开ie,选择“工具”菜单里的“internet选项”,然后在弹出的对话框里点击“设置”按钮,在设置对话框里点击“查看”钮,就会打开一个窗口显示浏览器放在硬盘里的所有缓存数据,其中就有大量的cookie文件。

所以奉劝大家不要将敏感的用户数据存放在cookie中,要么就通过加密将这些数据保护起来。

在以前的asp版本中没有加密的功能,现在.net构架在system.security.cryptography命名空间里提供了许多加密类可以利用。




一、.net的密码系统概要

简单地说,加密就是将原始字符(字节)串转变为完全不同的字符串的处理过程,达到原始字符无法破译的目的。这个处理过程是用另一个字符串(称为“密钥”),采取复杂的、混合的算法,“捣进”原始字符串。有时还使用一个称为“初始向量”的字符串,在密钥捣进之前先打乱目标字符串,预防目标字符串中较明显的内容被识破。加密的功效取决于所用密钥的大小,密钥越长,保密性越强。典型的密钥长度有64位、128位、192位、256位和512位。攻击者唯一的方法是创建一个程序尝试每一个可能的密钥组合,但64位密钥也有72,057,594,037,927,936种组合。

目前有两种加密方法:对称加密(或称私有密钥)和非对称加密(或称公共密钥)。对称加密技术的数据交换两边(即加密方和解密方)必须使用一个保密的私有密钥。非对称加密技术中,解密方向加密方要求一个公共密钥,加密方在建立一个公共密钥给解密方后,用公共密钥创建唯一的私有密钥。加密方用私有密钥加密送出的信息,对方用公共密钥解密。保护http传输安全的ssl就是使用非对称技术。

我们对cookie数据的加密采取对称加密法。.net构架从基本的symmetricalgorithm类扩展出来四种算法:

·system.security.cryptography.des

·system.security.cryptography.tripledes

·system.security.cryptography.rc2

·system.security.cryptography.rijndael

下面将示范des和tripledes算法。des的密钥大小限制在64位,但用于cookie的加密是有效的。tripledes完成了三次加密,并有一个较大的密钥位数,所以它更安全。使用那一种算法不仅要考虑加密强度,还要考虑cookie的大小。因为加密后的cookie数据将变大,并且,密钥越大,加密后的数据就越大,然而cookie数据的大小限制在4kb,这是一个必须考虑的问题。再者,加密的数据越多或算法越复杂,就会占有更多的服务器资源,进而减慢整个站点的访问速度。

二、创建一个简单的加密应用类

.net的所有加密和解密通过cryptostream类别来处理,它衍生自system.io.stream,将字符串作为以资料流为基础的模型,供加密转换之用。下面是一个简单的加密应用类的代码:

imports system.diagnostics

imports system.security.cryptography

imports system.text

imports system.io


public class cryptoutil


'随机选8个字节既为密钥也为初始向量

private shared key_64() as byte = {42, 16, 93, 156, 78, 4, 218, 32}

private shared iv_64() as byte = {55, 103, 246, 79, 36, 99, 167, 3}


'对tripledes,采取24字节或192位的密钥和初始向量

private shared key_192() as byte = {42, 16, 93, 156, 78, 4, 218, 32, _

15, 167, 44, 80, 26, 250, 155, 112, _

2, 94, 11, 204, 119, 35, 184, 197}

private shared iv_192() as byte = {55, 103, 246, 79, 36, 99, 167, 3, _

42, 5, 62, 83, 184, 7, 209, 13, _

145, 23, 200, 58, 173, 10, 121, 222}


'标准的des加密

public shared function encrypt(byval value as string) as string

if value <> "" then

dim cryptoprovider as descryptoserviceprovider = _

new descryptoserviceprovider()

dim ms as memorystream = new memorystream()

dim cs as cryptostream = _

new cryptostream(ms, cryptoprovider.createencryptor(key_64, iv_64), _

cryptostreammode.write)

dim sw as streamwriter = new streamwriter(cs)


sw.write(value)

sw.flush()

cs.flushfinalblock()

ms.flush()


'再转换为一个字符串

return convert.tobase64string(ms.getbuffer(), 0, ms.length)

end if

end function



'标准的des解密

public shared function decrypt(byval value as string) as string

if value <> "" then

dim cryptoprovider as descryptoserviceprovider = _

new descryptoserviceprovider()


'从字符串转换为字节组

dim buffer as byte() = convert.frombase64string(value)

dim ms as memorystream = new memorystream(buffer)

dim cs as cryptostream = _

new cryptostream(ms, cryptoprovider.createdecryptor(key_64, iv_64), _

cryptostreammode.read)

dim sr as streamreader = new streamreader(cs)


return sr.readtoend()

end if

end function


'triple des加密

public shared function encrypttripledes(byval value as string) as string

if value <> "" then

dim cryptoprovider as tripledescryptoserviceprovider = _

new tripledescryptoserviceprovider()

dim ms as memorystream = new memorystream()

dim cs as cryptostream = _

new cryptostream(ms, cryptoprovider.createencryptor(key_192, iv_192), _

cryptostreammode.write)

dim sw as streamwriter = new streamwriter(cs)


sw.write(value)

sw.flush()

cs.flushfinalblock()

ms.flush()


'再转换为一个字符串

return convert.tobase64string(ms.getbuffer(), 0, ms.length)

end if

end function



'triple des解密

public shared function decrypttripledes(byval value as string) as string

if value <> "" then

dim cryptoprovider as tripledescryptoserviceprovider = _

new tripledescryptoserviceprovider()


'从字符串转换为字节组

dim buffer as byte() = convert.frombase64string(value)

dim ms as memorystream = new memorystream(buffer)

dim cs as cryptostream = _

new cryptostream(ms, cryptoprovider.createdecryptor(key_192, iv_192), _

cryptostreammode.read)

dim sr as streamreader = new streamreader(cs)


return sr.readtoend()

end if

end function


end class

上面我们将一组字节初始化为密钥,并且使用的是数字常量,如果你在实际应用中也这样做,这些字节一定要在0和255之间,这是一个字节允许的范围值。

三、创建一个cookie的应用类

下面我们就创建一个简单的类,来设置和获取cookies。

public class cookieutil


'设置cookie *****************************************************


'settripledesencryptedcookie (只针对密钥和cookie数据)

public shared sub settripledesencryptedcookie(byval key as string, _

byval value as string)

key = cryptoutil.encrypttripledes(key)

value = cryptoutil.encrypttripledes(value)


setcookie(key, value)

end sub


'settripledesencryptedcookie (增加了cookie数据的有效期参数)

public shared sub settripledesencryptedcookie(byval key as string, _

byval value as string, byval expires as date)

key = cryptoutil.encrypttripledes(key)

value = cryptoutil.encrypttripledes(value)


setcookie(key, value, expires)

end sub



'setencryptedcookie(只针对密钥和cookie数据)

public shared sub setencryptedcookie(byval key as string, _

byval value as string)

key = cryptoutil.encrypt(key)

value = cryptoutil.encrypt(value)


setcookie(key, value)

end sub


'setencryptedcookie (增加了cookie数据的有效期参数)

public shared sub setencryptedcookie(byval key as string, _

byval value as string, byval expires as date)

key = cryptoutil.encrypt(key)

value = cryptoutil.encrypt(value)


setcookie(key, value, expires)

end sub



'setcookie (只针对密钥和cookie数据)

public shared sub setcookie(byval key as string, byval value as string)

'编码部分

key = httpcontext.current.server.urlencode(key)

value = httpcontext.current.server.urlencode(value)


dim cookie as httpcookie

cookie = new httpcookie(key, value)

setcookie(cookie)

end sub


'setcookie(增加了cookie数据的有效期参数)

public shared sub setcookie(byval key as string, _

byval value as string, byval expires as date)

'编码部分

key = httpcontext.current.server.urlencode(key)

value = httpcontext.current.server.urlencode(value)


dim cookie as httpcookie

cookie = new httpcookie(key, value)

cookie.expires = expires

setcookie(cookie)

end sub


'setcookie (只针对httpcookie)

public shared sub setcookie(byval cookie as httpcookie)

httpcontext.current.response.cookies.set(cookie)

end sub


'获取cookie *****************************************************


public shared function gettripledesencryptedcookievalue(byval key as string) _

as string

'只对密钥加密

key = cryptoutil.encrypttripledes(key)


'获取cookie值

dim value as string

value = getcookievalue(key)

'解密cookie值

value = cryptoutil.decrypttripledes(value)

return value

end function


public shared function getencryptedcookievalue(byval key as string) as string

'只对密钥加密

key = cryptoutil.encrypt(key)


'获取cookie值

dim value as string

value = getcookievalue(key)

'解密cookie值

value = cryptoutil.decrypt(value)

return value

end function


public shared function getcookie(byval key as string) as httpcookie

'编码密钥

key = httpcontext.current.server.urlencode(key)

return httpcontext.current.request.cookies.get(key)

end function


public shared function getcookievalue(byval key as string) as string

try

'编码在getcookie里完成

'获取cookie值

dim value as string

value = getcookie(key).value

'解码所存储的值

value = httpcontext.current.server.urldecode(value)

return value

catch

end try

end function


end class

上面的设置功能中,有些功能附加提供了cookie有效期这个参数。不设置该参数,cookie将只为浏览器会话才保存在内存中。为了设置永久的cookie,就需要设置有效期参数。

上面我们对密钥和cookies值进行了编码与解码,其原因是cookies与urls有同样的限制,字符“=”和“;”是保留的,不能使用。这在保存加密后的数据时尤其重要,因为加密算法将添加“=”,按所分配块的大小来填满该数据块。

好了,你会保护cookies数据了吧?
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表