Digest authorization in SIP with MD5

When SIP requests (like INVITE or REGISTER) are issued the SIP gateway server
can send back 407 Proxy Authentication Required or 401 Unauthorized.

In this case RFC compliant UA must:

1) Send ACK response to the server response to close the transaction.

2) Repeat the initial request and provide additional Authorization (for 401) or Proxy-Authorization (for 407) header in this message. This request must be sent with the same Call-ID and To, From headers as the original one. However, CSeq value must be incremented.

Generation of Authorization header

Regarding generation of Authorization header. From now on, the explanation of generation of Proxy-Authorization header (for 407 server response) is omitted because it is completely identical to scheme described below except “Authorization” header name must be changed to “Proxy-Authorization”.

In 401 Unauthorized server response, the SIP server must provide Authenticate header which will contain parameters of the authorization mechanism supported by server.

SIP servers usually offer Digest authorization scheme which implies that
client does not send user credentials in an open form but calculates digest value which is transmitted on the channel.
The digest value is calculated according to the algorithm specified by server.
When no algorithm is specified in Authenticate header it is assumed that MD5 is used to create digest value.


 Authenticate: Digest realm="name_of_realm", nonce="123456AB"

For the example specified above, client is required to form Authorization header containing scheme name, username, realm, URI, server supplied nonce value, nonce counter and digest response string. This digest response string is the product of the algorithm specified (or MD5 by default) in Authentication scheme.

Example of authorization header:

Authorization: Digest username="alexander",realm="name_of_realm", uri="sip:128-195-155-11",

Generation of digest response

Digest response for MD5 based authorization is generated as follows.

1) First MD5 value is calculated as shown below and converted to HEX representation:

	string strH1;
	MD5("username:name_of_realm:password", (char *) pBinaryBuffer);
	BINARY_TO_HEX((char *) pBinaryBuffer, strH1);

2) Second MD5 value is calculated as shown below and converted to HEX representation.
The input for the MD5 function contains SIP request name, and some URI.


I believe the URI is not a meaningful value here. The only rule that worked for me
is that URI string which is passed to MD5 must be exactly the same as it is specified in
Authorization header. And I am not sure that full qualified SIP URI will work
for most SIP servers. Instead of REGISTER method there could be INVITE.

	string strH2;
	MD5("REGISTER:sip:128-195-155-11", pBuffer);
	BINARY_TO_HEX(pBuffer, strH2);

3) Third MD5 is calculated using server nonce value which was supplied in the Authenticate header
in the server 401 response. Note, that nonce value is not converted to binary form and only taken
as a string as it was provided.

	string strH3;
	MD5(strH1 + ":" + strNonce + ":" + strH2, pBuffer);
	BINARY_TO_HEX(pBuffer, strH3);
	string DigestResponse = strH3;

After the digest response is created it is included in the authorization header.

When there are problem with provided credentials server can send back 403 Forbidden response.
Otherwise if user is authorized successfuly server should process the request as usual.

6 Responses to “Digest authorization in SIP with MD5”

  1. Kutay says:


    Thank you for you short description for this algorithm however, the way that I calculated response parameter is not work for IMS Client. I mean our responses become different after calculation. When I compare my response and client’s response, they seem different.


    I do not know how to generate following messages’ response parameter:

    REGISTER sip:ericsson.com SIP/2.0
    Max-Forwards: 20
    CSeq: 1 REGISTER
    Expires: 3600
    Content-Length: 0
    Contact: “Alice” ;+sip.instance=e7def040-f226-4927-bd52-a37f0fdf0067
    Authorization: Digest username=”alice@ericsson.com”,realm=”ericsson.com”,nonce=”",response=”",uri=”sip:ericsson.com”
    User-Agent: Fokus MONSTER Version: 0.9.13
    From: “Alice” ;tag=1000
    To: “Alice”
    Call-ID: c7fd832a2175d36d8bac9c8f4bfced2d@
    Via: SIP/2.0/UDP;branch=z9hG4bK3b39625cc9b75f78d0789f5a93554dfb3536

    [SDS] [INFO ]
    <– Sent message on UDP [Local: | Remote:] [[[
    SIP/2.0 401 Unauthorized - Respond to challenge
    CSeq: 1 REGISTER
    Via: SIP/2.0/UDP;branch=z9hG4bK3b39625cc9b75f78d0789f5a93554dfb3536;received_port_ext=5081;received=
    WWW-Authenticate: Digest realm="ericsson.com",stale=false,algorithm=MD5,nonce="fe176678b1b5fe0738666a70e05248c4",opaque="d77e6f9d33d5f3baadf33be71aa52403",domain="sip:ericsson.com",qop="auth"
    Content-Length: 0
    Call-ID: c7fd832a2175d36d8bac9c8f4bfced2d@
    From: "Alice" ;tag=1000
    To: "Alice";tag=5066

    [SDS] [INFO ]
    –> Received message on UDP [Local: | Remote:] [[[
    REGISTER sip:ericsson.com SIP/2.0
    Max-Forwards: 20
    CSeq: 2 REGISTER
    Expires: 3600
    Content-Length: 0
    Contact: “Alice” ;+sip.instance=e7def040-f226-4927-bd52-a37f0fdf0067
    Authorization: Digest username=”alice@ericsson.com”,realm=”ericsson.com”,nonce=”fe176678b1b5fe0738666a70e05248c4″,uri=”sip:ericsson.com”,opaque=”d77e6f9d33d5f3baadf33be71aa52403″,algoritm=MD5,response=”16e5c07af53f578bf1c08dedc636ffa7″,qop=auth,nc=00000001,cnonce=”101102559755515299″
    User-Agent: Fokus MONSTER Version: 0.9.13
    From: “Alice” ;tag=1001
    To: “Alice”
    Call-ID: a00e832b3171be59068820bba40887de@
    Via: SIP/2.0/UDP;branch=z9hG4bKf739c2091e946a283db7449f256244003536

  2. Kutay says:

    In this example, response is:

    but when I use your algorithm I found something different….

    Do you know why?


  3. [...] I needed to work out the MD5 Digest hash for SIP authorisation. A quick search on Google revealed instructions on how to generate the hash, and then I made this simple PHP [...]

  4. This was a really helpful post… i saved my reading the entire RFCs man. Thanks a ton. :)

  5. Hi,
    I find your post rather incomplete. he formula you described above only applies when the value of qop is empty or undefined. When the value of qop is auth, then the response is generated by the following formula:
    response = md5(md5(username:realm:password):nonce:nonceCount:clientNonce:qop:md5(method:URI))

  6. [...] This script mostly follows information gleamed from this article. [...]

RSS feed for comments on this post. And trackBack URL.

Leave a Reply