Protocols/MSNP/Reference/Relying Party Suite
MSNP Protocol |
Introduction • Terms • Clients |
Reference |
Error List • Commands • Relying Party Suite • Spotlife |
Services |
XMPP • HTTP Gateway • Tabs • Activities |
Documentation |
Development Tools • MSNP Grid |
Polygamy • URLs used by MSN |
Documents |
Protocol Versions |
Version 21 |
Version 18 |
Version 16 |
Version 15 |
Version 14 |
Version 13 |
Version 12 |
Version 11 |
Version 9 |
Version 8 |
Version 2 |
MSNC |
Introduction • P2P • Object Descriptor • Display Pictures • File Transfer |
Scenarios |
Microsoft Messenger for Mac |
MSNP on WebTV (MSNTV) |
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 messengerclear.live.com
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] [...]