Digest Authentication (RFC 2831)

Jp Calderone exarkun at intarweb.us
Sat Sep 27 09:15:53 CEST 2003


  I've been trying to implement support for this authentication scheme for a
little while now, and in the last couple days I've been completely stumped.

  I know about the digest authentication code in urllib2, and while I'd like
to use it directly, it is too closely tied to HTTP for my needs.

  I have taken hints from the code, but I am still stuck with something that
doesn't recognize correct challenge responses as correct.

  I've reduced the problem to this code:

    user = "exarkun"
    passwd = "password"
    realm = "intarweb.us"
    nonce = "abcdefg"
    qop = "auth"
    method = "REGISTER"
    uri = "sip:exarkun at intarweb.us"

    nc = cnonce = ''

    def H(s):
        return md5.md5(s).digest()

    def KD(k, s):
        return H(k + ":" + s)

    def HEX(s):
        return s.encode('hex')

    def A1(user, realm, passwd, nonce, cnonce):
        r = H(user + ":" + realm + ":" + passwd)
        return r + ":" + nonce + ":" + cnonce

    def A2(uri, method):
        return method + ":" + uri

    def RESP(a1, nonce, nc, cnonce, qop, a2):
        r = nonce + ":" + nc + ":" + cnonce + ":" + qop + ":"
        return HEX(KD(H(a1), r + HEX(H(a2))))

    def g():
        return RESP(
            A1(user, realm, passwd, nonce, cnonce),
            nonce, nc, cnonce, qop, A2(uri, method)
        )

    correct = '8cf8b637395da8475d65aaf45e4cfad5'

    v = g()
    print v == correct
    print correct
    print v
    
  It is, essentially, a straight translation from the RFC, but I have been
unable to get it to produce the given correct value for the given inputs. 
One sticking point seems to be that the client authenticating against me
omits both the nc and cnonce values.  If there is a standard correct way of
computing the digest without those values, it does not seem to be covered by
the RFC.  I have tried the obvious approaches of simply removing them,
supplying "" as their value, etc, but nothing works.

  I am on the verge of breaking down the md5() calls so I can discover the
point of failure more accurately, but before I did that I was hoping I might
find someone who has implemented this before and could give me some hints.

  Any help is appreciated,

  Jp

-- 
No, `Eureka' is Greek for `This bath is too hot.'
                -- Dr. Who
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20030927/0f830ea6/attachment.pgp>


More information about the Python-list mailing list