Notification server

Challenges

The MSN servers will periodically send a message to the client to verify that it is an official client. This message is received as a "CHL" command and must be replied to with a "QRY" command. The method for calculating the response outlined below has been in effect since MSNP11.

Challenges are also used to verify the validity of a client when sending OIM's.

Protocol Sequence

Server:
<<< CHL 0 ChallengeString\r\n
Client:
>>> QRY TrID ProductID PayloadLength\r\n
    MD5Digest
Server:
<<< QRY TrID\r\n
  • TrID: The TransactionID of the command.
  • ChallengeString: A string required for the response
  • ProductID: Client identification string
  • PayloadLength: Size of the payload, always 32 because MD5 hashes are constant in length
  • MD5Digest: MD5 digest as calculated below

Calculating Response

In order to calculate a response, you must be able to manipulate 64-bit integers, using them for bitwise operations as well as basic math. Additionally, you will need an implementation of the MD5 hashing algorithm. Note: while MD5 hashes are generally written out as 32-character hexadecimal strings, this is purely for presentation's sake. This document will assume the MD5 hash has been left in its binary form, that is, 128 bits or 16 bytes of data.

MD5 Hash

The first step in the process of creating the challenge response is creating an MD5 digest from the ChallengeString (from the server's CHL command) followed by a special key, called the "Product Key". This Product Key is specific to every version of the MSN client.

The MD5 hash can then be split into 4 32-bit unsigned integers in little-endian format. You should then bitwise AND each of these integers with 0x7FFFFFFF and save the result.

The Product ID

The Product ID is another string specific to every version of the MSN client. This string is sent in the QRY command, and is used to calculate the 64-bit key.

First, take the challenge data and append the Product ID to it. This string is then padded with '0' (not 'NULL'!) until its length is a multiple of 8. The string should be split into an array of 32-bit unsigned little-endian integers.

The 64-bit Key

In the third step in the process we are going to create a key based on the data from the previous steps. You will need two variables, called High and Low, both initialized to 0. Note: High and Low must be 64-bit variables because they may hold very large values. We will loop through the previous data array two elements at a time, calling the current element N and the element after it N + 1.

The first step in the loop should be to create a temporary variable and fill it with the value of piece N, multiply it by 0x0E79A9C1, modulo 0x7FFFFFFF and add the variable Low to it (which will be 0 the first run). After this, multiply the temporary variable by the first element of the MD5 hash and add the second element of the MD5 hash, again modulo 0x7FFFFFFF.

Next, calculate the high part of the key. This can be done by filling the variable Low with the value of piece N + 1. Add the temporary variable to it, modulo 0x7FFFFFFF. Multiply it by the value of the third element of the MD5 hash and add the fourth element of the MD5 hash to it, again modulo 0x7FFFFFFF.

At the end of the loop, add the values from the variable Low and the temporary variable to High.

After the loop, add the second element of the MD5 hash to Low and the fourth element to High, both modulo 0x7FFFFFFF.

To create the key, take the variables High and Low, and treat them as one large 64-bit integer.

The Final Result

The final step in the process is to create the new challenge hash.

First, the MD5 hash must be split in two parts (both 8 bytes long). You can treat each of these parts as a 64-bit little-endian integer, which should then be XOR'd with the key.

This result should be converted to its hexadecimal string representation (Each byte becomes two characters representing its hexadecimal value). If the string is less than 32 characters in length you need to prefix it with '0' (again, not NULL). This final result is the MD5Digest that is sent as the payload of the QRY command.

Example

Server:
<<< CHL 0 22210219642164014968\r\n

Using the MSNP15 Product Key, the MD5 Hash is:

67780f8e134b77b535a64c7c0f7f1eb0

Treating this as four integers gives:

0x0e0f7867  (235894887)
0x35774b13  (897010451)
0x7c4ca635 (2085398069)
0x301e7f0f  (807304975)

Using the Product ID gives:

0x31323232  (825373234)
0x39313230  (959525424)
0x31323436  (825373750)
0x31303436  (825242678)
0x38363934  (943077684)
0x444f5250 (1146049104)
0x39313130  (959525168)
0x554a5347 (1430934343)
0x38312443  (942744643)
0x30303030  (808464432)

The 64-bit key is:

High: 0x08188389 (135824265)
Low:  0x0ea078c3 (245397699)
Key:  0x081883890ea078c3 (583360776423635395)

The final result is:

a400af809ac86fbdf6deec7286fc06b8
Client:
>>> QRY 5 PROD0119GSJUC$18 32\r\n
    a400af809ac86fbdf6deec7286fc06b8
Server:
>>> QRY 5\r\n

Product Key and ID

MSNP15 is currently used by Windows Live Messenger version 8.5.1288.816. The Product Key and ID for that particular version are:

Product Key: ILTXC!4IXB5FB*PX
Product ID:  PROD0119GSJUC$18