一、口令认证常见机制

基于口令认证的系统一般有以下几种口令验证方式:

1、客户端以明文形式将用户名密码通过网络发送到服务器,服务器与已经保存在服务端的用户名密码进行比较,一致则通过验证;

HTTP基本鉴别方案即采用这种方式,它不会对以明文方式在物理网络中传输的实体进行任何形式的保护,显然这不是安全的用户鉴别方式。

2、客户端对用户名和密码进行加密,服务端解密后在验证;

这种方式有一定的安全性,但无论加密方式采用对称加密方式(如DES),还是非对称加密方式(如:MD5),都不足够安全。

对称加密方式容易被破解,非对称加密方式虽然很难被破解,但仍然会受到字典攻击和假冒服务器攻击。

3、密码+动态口令机制

HTTP摘要认证方案即采用该种方式,虽然它并不象Kerberos或任何客户端的私钥方案那样安全,但是它比telnet、ftp用的机制好,当然,也比基本鉴别方案安全。

SIP协议也采用该摘要认证方案,其中rfc2543允许Sip实现者可以使用HTTP的basic和digest鉴权机制来提供初步的安全机制。

但rfc3261要求服务器必须不能接收验证方式为“basic”类型的信任书,并且服务器必须拒绝“basic”。

此外,摘要认证方案并没有为最初用户和服务器间的口令建立提供安全做法。

二、SIP协议摘要认证机制

前面提到SIP协议采用的摘要认证方案是一种类似于密码+动态口令的机制,其关键点在于:

1、服务器在收到对受保护对象未经认证的访问请求时,在应答中提供一个动态的nonce值(相当于动态口令),为防止回放攻击,该值最好不要重复;

2、客户端想重试发送请求时,也产生一个动态的cnonce值,用来避免选择纯文本攻击、提供共同鉴别、提供某些消息的完整性保护;

3、客户端通过计算生成response值(即摘要),用来证明用户是否知道口令。

4、服务器收到重发的请求后,要对用户名、口令的合法性进行检查。这时,服务器使用已经保存在服务端的用户名和密码并结合消息头中的其他参数采用

和客户端相同的摘要计算操作(如,MD5),并将结果与给定请求-摘要(response值)相比较即可。此处的关键点在于:由于response的值与用户名、

密码、nonce、cnonce、algorithm(约定的算法)等参数有关,因此如果结果一致,服务器和客户端双方都可以认为对方不是伪造的。

三、response的计算方法

(请参考rfc2617 3.2.2节):

1、response                = "response" "=" request-digest

2、请求-摘要(Request-Digest)

   a、如果”qop”值是"auth" 或"auth-int":

  request-digest = <"> < KD ( H(A1), unq(nonce-value)
   ":" nc-value
   ":" unq(cnonce-value)
   ":" unq(qop-value)
   ":" H(A2)
   ) <">

   b、如果”qop”指示没有给出(与RFC2069保持兼容性):

  request-digest =<"> < KD ( H(A1), unq(nonce-value)
  ":" H(A2)
  ) <">

     解释:KD(secret, data)表示对数据"data"和"secret"调用摘要算法获取字符串,用H(data)表示对数据"data"调用校验和算法获取字符串;

而unq(X)表示将带引号字符串的引号去掉。

     对于"MD5" 和"MD5-sess" 算法: H(data) = MD5(data)

     并且KD(secret, data) = H(concat(secret, ":", data)) 也就是说,摘要(digest)就是对secret与data通过冒号连接一起的结果进行MD5运算。

而"MD5-sess"算法则允许其它第三方服务器参与鉴别。

   A1及A2的定义在下面。

3、A1

   如果算法("algorithm")值是”MD5”或没有指定,则A1是:

  A1 = unq(username-value) ":" unq(realm-value) ":" passwd

  其中  passwd = < user's password >

  如果"algorithm"值是"MD5-sess",则A1只要计算一次,即当客户端发出第一个请求,并从服务器收到WWW-鉴别(WWW-Authenticate)质询(challenge)时计算。它使用该质询

中的服务器的nonce,则用来构建A1的第一个客户端nonce值应为:

  A1 = H( unq(username-value) ":" unq(realm-value)

   ":" passwd )

   ":" unq(nonce-value) ":" unq(cnonce-value)

   上式为并发请求和回应的鉴别产生一个‘会话密钥’(session key),该密钥对于每个‘鉴别会话’(authentication session)都是不同的,这样,就限制了使用任何一个密钥进行哈希处理

的次数。
4、 A2

如果”qop”值是”auth”或者没给出,则A2:

A2 = Method ":" digest-uri-value 

如果"qop"值是"auth-int", 则A2:

A2 = Method ":" digest-uri-value ":" H(entity-body)

5、项值和带引号的字符串(Directive values and quoted-string)

注意,许多项的取值,如”username-value”等,被定义成带引号的字符串(quoted-string)。而实际上,”unq”注释则表示在生成字符串A1时,去掉其外部的引号。因而,如当授权报头包

括该域,如:

  username="Mufasa", realm=myhost@testrealm.com

则表示用户Mufasa的口令是"Circle Of Life",这样H(A1)就可表示成

  H(Mufasa:myhost@testrealm.com:Circle Of Life),注意,在摘要字符串中没有引号。

  注意,在摘要函数H()中的字符串中不允许出现空格,除非空格出现在带引号的字符串内或者用以标记字符串摘要的实体主体中。例如,上面出现的字符串A1必须是

  Mufasa:myhost@testrealm.com:Circle Of Life

在冒号的两边都不可以有空格,但是允许口令单词之间出现空格(Circle+SP+Of+SP+Life)。同样,其它由H()摘要的字符串也不能在用于域间分隔的冒号两边加空格,除非空格在引号内

或被摘要的实体主体内。

   同样要注意的是,如果应用了完整性保护(integrity protection),即qop=auth-int,则H(实体-主体)就是实体主体的哈希值,而不是消息主体的哈希值,该值在发送方进行任何传

输编码前计算,之后,被接收方删除。