Protocols/MSNP/Reference/Relying Party Suite

From NINA Wiki
Jump to navigation Jump to search
MSNP Protocol
Error ListCommandsRelying Party SuiteSpotlife
XMPPHTTP GatewayTabsActivities
Development ToolsMSNP Grid
PolygamyURLs used by MSN
Protocol Versions
Version 21
Version 18
Version 16
Version 15
Version 14
Version 13
Version 12
Version 11
Version 9
Version 8
IntroductionP2PObject DescriptorDisplay PicturesFile Transfer
Microsoft Messenger for Mac

Relying Party Suite, also known as RPS or SSO (Single Sign-On) authentication is a challenge-response method introduced in MSNP15 and stayed in the protocol as a primary authentication mechanism up to when MSNP21 was unveiled (and past the MSN realm, MSNP22 but as a secondary mechanism and possibly not used officially). The mechanism involves retrieving a challenge string from the notification server, authenticating through a web service to get a binary secret and hashing it with several HMAC hash functions, and using the resulting HMAC hash to encrypt the challenge string and store it in a binary structure that's then encoded and sent back to the notification server to complete the login process.

Logging in on MSNP

When logging in on MSNP15+, you send a USR SSO I command with your email address as a parameter, and in return should get a USR SSO S with a policy and a challenge string, which is usually a randomly generated Base64-encoded value (in our implementation we simply generate 48 random bytes of data and Base64-encode it):

<<< USR [TrID] SSO I [email]
>>> USR [TrID] SSO S [policy] [challenge string]

The policy is used when querying the web service for the binary secret and tokens, but the challenge string itself is a crucial part of the RPS process and necessary for creating the end result.

Web Service

After this is sent, authentication to a web service is performed, which in the case of official MSN clients is done on RST.srf. The technical details of how that works as a whole is out of this document's scope, but for our purposes we'll summarize how it works. The requesting client supplies account credentials and a list of domains to authenticate to, and the service returns the tokens for each domain if successful. In the domain, there's also a unique binary secret defined that the client will need for RPS authentication.

Encrypt Binary

Once the binary secret is obtained, it has to be Base64-decoded and used to derive a TripleDES key used in the encryption process. The process for this involves SHA1-HMAC using the decoded binary secret as a key, and goes as follows:

- Hash the message WS-SecureConversationSESSION KEY HASH with SHA1-HMAC - this will be referred to as hash1 - Hash a concatenation of hash1 and the same message from before with SHA1-HMAC - this will be referred to as hash2 and will be needed later on - Hash hash1 with SHA1-HMAC - this will be referred to as hash3 - Hash a concatenation of hash3 and the same message used to create hash1 with SHA1-HMAC - this will be referred to as hash4 and will be needed later on.

After creating all 4 hashes, the first 20 bytes of hash2 and the first 4 bytes of hash4 have to be combined to create the resulting key. This will be referred to as key2 in this document (key1 would be the binary secret). key3 is generated in a similar way, but the only difference is that the starting message is WS-SecureConversationSESSION KEY ENCRYPTION instead of WS-SecureConversationSESSION KEY HASH.

Now the client is at the stage where it has to start creating the hash and cipher responses to send back to the notification server. To create the hash response, an SHA1-HMAC is performed on the challenge string retrieved earlier, using key2 as the key. Before creating the cipher response, TripleDES encryption capable of utilizing CBC mode will have to be set up, and PKCS#5 padding for messages will have to be implemented. A random 8-byte value will also have to be generated as an IV for the encryption process. To create the cipher, the challenge string has to be encrypted with key3 as the key and the randomly generated value as the IV.

The IV, final hash, and cipher are then bundled up in a struct, with all packed values being little endian and unless stated otherwise, are unsigned 32-bit integers.

structHeaderSize (4 bytes) - Counts the length of the header (the data before the IV/cipher and hash). The length includes the length of this value.

cryptMode (4 bytes) - Defines the mode the encryption algorithm operated under. Typical value has been observed as CRYPT_MODE_CBC (0x00000001).

cipherType (4 bytes) - Defines the type of encryption algorithm used to generate the cipher. Typical value has been observed as 0x6603 (TripleDES).

hashType (4 bytes) - Defines the type of hash algorithm used to generate the hash. Typical value has been observed as 0x8004 (SHA-1).

ivLen (4 bytes) - Length of the IV in the struct. Typical value has been observed as 8.

hashLen (4 bytes) - Length of the hash in the struct. Typical value has been observed as 20.

cipherLen (4 bytes) - Length of the cipher in the struct. Typical value has been reported as 72, but can and will change depending on the length of the challenge string that has been encrypted.


ivBytes (variable-length, but usually 8 bytes) - A byte array containing the IV used to create the cipher.

hashBytes (variable-length, but usually 20 bytes) - A byte array containing the hash response generated.

cipherBytes (variable-length) - A byte array containing the cipher generated.

Response to MSNP

This value is then Base64-encoded and sent along with some other parameters in a USR SSO S to the server to be verified:

<<< USR [TrID] SSO S [token] [base64-encoded struct] [...]