-
Notifications
You must be signed in to change notification settings - Fork 79
Messages
A message is a (non-JSON) string that consists of a single MSL header followed by zero or more payload chunks carrying application data. Messages with the handshake flag set will have zero payload chunks. All other messages must contain at least one payload chunk.
header
payloadchunk*
Parsing a message is done by performing sequential JSON parse operations on the message string. Since the header and payload chunk byte lengths are unknown (as JSON encoding does not define a fixed length), they can only be extracted by attempting to parse the message.
Entities are allowed to send multiple messages in parallel. Communication may simultaneously occur with multiple entities across multiple MSL networks. Messages may be simultaneously created with different combinations of entity authentication data or master tokens, user ID tokens, and service tokens.
The MSL header carries all MSL data used for entity and user authentication, message encryption and verification, and service tokens. Portions of the MSL header are encrypted.
header = {
"#mandatory" : [ "headerdata", "signature" ],
"#conditions" : [ "entityauthdata xor mastertoken" ],
"entityauthdata" : entityauthdata,
"mastertoken" : mastertoken,
"headerdata" : "binary",
"signature" : "binary"
}
Field | Description |
---|---|
entityauthdata | entity authentication data (entityauthdata) |
headerdata | header data or ciphertext envelope containing the header data (headerdata) |
mastertoken | master token (mastertoken) |
signature | signature envelope verifying the headerdata |
The MSL header is encrypted and verified according to the entity authentication data or master token included in the MSL header. Some entity authentication schemes do not support encryption or verification.
Only one of the entity authentication data or master token should appear in a MSL header. If both fields are present the master token takes precedence and the entity authentication data is ignored.
headerdata = {
"#mandatory" : [ "messageid", "renewable", "handshake" ],
"messageid" : "int64(0,2^53^)",
"nonreplayableid" : "int64(0,2^53^)",
"renewable" : "boolean",
"handshake" : "boolean",
"capabilities" : capabilities,
"timestamp" : "int64(0,2^53^)",
"keyrequestdata" : [ keyrequestdata ],
"keyresponsedata" : keyresponsedata,
"userauthdata" : userauthdata,
"useridtoken" : useridtoken,
"servicetokens" : [ servicetoken ],
"peermastertoken" : mastertoken,
"peeruseridtoken" : useridtoken,
"peerservicetokens" : [ servicetoken ]
}
Field | Description |
---|---|
capabilities | sender’s message capabilities (capabilities) |
handshake | handshake message |
keyrequestdata | session key request data (keyrequestdata) |
keyresponsedata | session key response data (keyresponsedata) |
messageid | message ID |
nonreplayableid | non-replayable ID |
peermastertoken | peer master token (mastertoken) |
peerservicetokens | peer service tokens (servicetoken) |
peeruseridtoken | peer user ID token (useridtoken) |
renewable | master token and user ID token renewable |
servicetokens | service tokens (servicetoken) |
timestamp | creation time in seconds since the epoch |
userauthdata | user authentication data (userauthdata) |
useridtoken | user ID token (useridtoken) |
The header creation timestamp based off the sender’s clock. The recipient may use this value to determine if master tokens and user ID tokens issued by the sender are renewable or expired.
There is no guarantee the sender time is the real time and the existence of this value does not imply the sender and recipient times should be synchronized.
The message ID is a number against which payload chunks are bound.
To protect against replay, if the message is a response to another message, the message ID of the response message must be equal to the message ID of the request message plus one. When incrementing the message ID for a response message, the maximum message ID is equal to 253 after which it wraps around to 0. If the message ID of a response message does not equal the expected value the receiving entity must reject the message.
Otherwise the message ID must be a random number.
This value is set in messages sent by a master token entity if it wishes the message to be non-replayable. It is an increasing number associated with the entity identity and serial number of the master token, and the initial value is 1. When incrementing the non-replayable ID the maximum non-replayable ID is equal to 253 after which it wraps around to 0.
The value may not be set if the message uses entity authentication data instead of a master token.
Upon receipt of a message containing a non-replayable ID, the issuer of the master token must check the value against the largest received non-replayable ID associated with the master token entity identity and serial number. If the value is greater than the largest received value by no more than 65536 the message is accepted and the current largest value is updated to equal the received non-replayable ID. Otherwise the message is rejected. The wrap around from 253 to 0 must be considered when comparing the non-replayable ID values.
To handle out-of-order receipt of non-replayable messages the master token issuing entity may also wish to accept messages with a non-replayable ID that is smaller than the largest received value if it is known that specific value has not already been received. This set of additional non-replayable IDs should be limited to prevent acceptance of very old messages. It is not necessary to support this behavior if it is acceptable to require serialization of non-replayable messages or to require the master token entity to resend rejected non-replayable messages with an newer non-replayable ID.
The master token issuing entity may discard the non-replayable ID value associated with a specific entity identity and master token serial number after it is sure the master token entity will no longer use a master token with that serial number.
This flag is set by a sender if it is prepared to accept a new master token and session keys, or a new user ID token, in response to this message. It does not indicate the response must return a new master token and session keys or a new user ID token. The master token and session keys can be renewed independent of the user ID token.
Setting this flag requires one or more key request data to be included in the message. One key request data should be included for each key exchange scheme the sender is willing to accept key response data for; the receiver will select the key exchange scheme it wishes to use if it decides to renew the session keys. If no key request data is included only the user ID token may be renewed.
If the master token is expired, and the renewal flag is not set, key request data is not included, or the issuing entity will not permit the master token to be renewed, then the message must be rejected.
If the user ID token is expired and the renewal flag is not set the user ID token will still be renewed.
Since there is often overhead associated with renewal operations for both entities involved, we wish to minimize the number of renewable messages without introducing additional network round trips. To accomplish this, the following logic is recommended:
When creating a message with a specific master token, if there are no messages in progress using that master token then send the message as renewable and include key request data. If there is at least on renewable message in progress using that master token then send the message as non-renewable.
This ensures there is at most one renewable message in progress for a specific master token.
As an optimization, the master token entity may choose to only send renewable messages when it is known that the master token is renewable. This optimization requires the master token entity to have some knowledge of the issuing entity time.
This flag is set true if the message is a handshake message and will not include any payload chunks. Handshake messages must set the renewable flag to true.
Key response data will be included in a message if a new master token and session keys have been issued. The new master token serial number must be used when processing any user ID token and service tokens included in the message. The new session keys must be used to verify and decrypt the message payloads.
In a trusted services network the key response data applies to the primary tokens. In a peer-to-peer network mode the key response data applies to the peer tokens.
The sender should include user authentication data or a user ID token in a message when the application data is user-specific or it wishes service tokens to be bound to the user. If user authentication data is included in a renewable message, and a master token or key response data will be included in the response, the recipient may issue and include a user ID token in the response.
Typically only one of the user authentication data or user ID token will appear in the MSL header data. If both are included then the user identified by the user authentication data must match the user identified by the user ID token.
User authentication data may only be included if the header data will be encrypted.
When creating a message all applicable service tokens will be included by default. The set of applicable service tokens is equal to:
- All service tokens that are not bound to a master token or user token.
- All service tokens that are bound to the master token used by the message and are not bound to a user ID token.
- All service tokens that are bound to both the master token and user ID token used by the message.
A service token is uniquely identified by the combination of name, whether or not it is bound to a master token, and whether or not it is bound to a user ID token. Therefore a message may include up to three service tokens with the same name as long as each service token is bound to the master token and to the user ID token differently from the others.
The application is free to exclude individual service tokens by name, add new service tokens, or specify tokens for deletion prior to sending the message. Note that excluding a service token from a message is different than deleting one.
If a service would like the master token entity to delete a service token it sends a new service token with the same name, also bound to the master token and user ID token in the same way, but with zero-length token data. The master token entity may then remove any instances of the service token from its local state and should not include the service token on any messages it creates.
In a trusted services network, all services are implicitly trusted. Contrariwise all clients are implicitly untrusted and the server application must be able to deal with missing service tokens.
If a peer master token is included the recipient of the message is expected to use it as the master token of the reply. Similarly if a peer user ID token or peer service tokens are included the recipient is expected to use them as the user ID token and service tokens of the reply.
This is used in peer-to-peer configurations to allow each entity to identify itself to the other with correctly bound tokens: the peer user ID token must be bound to the peer master token or key response data master token; any master token- or user ID token-bound peer service tokens must be validated against the peer master token and peer user ID token.
The master token, user ID token, and service tokens of a request become the peer tokens of the reply.
capabilities = {
"compressionalgos" : [ enum(GZIP|LZW) ],
"languages" : [ "string" ],
"encoderformats" : [ "string" ],
}
Field | Description |
---|---|
compressionalgos | supported compression algorithms |
languages | preferred languages |
encoderformats | preferred MSL encoder formats |
The compression algorithms may be taken into consideration by the receiving entity when constructing a response to determine if it may compress application data.
The preferred languages are identified by BCP-47 language codes and listed in descending order of preference. The languages may be taken into consideration when constructing user-consumable error messages for inclusion in error messages.
The preferred MSL encoder formats listed in descending order of preference. The encoder formats should be honored when responding to a message.
Each payload chunk in a single message is individually packaged and independently encrypted and verified, but sequentially ordered. The application data may be optionally compressed prior to encryption.
Payload chunks are bound to a message by the MSL header message ID to prevent misuse.
If the message contains key response data, the payload chunks are encrypted using the new session encryption key and authenticated by an HMAC generated using the new session HMAC key.
If the message does not contain key response data and contains a master token, the payload chunks are encrypted using the session encryption key and authenticated by an HMAC generated using the session HMAC key.
If the message does not contain key response data and contains entity authentication data, the payload chunks are encrypted if the entity authentication scheme supports encryption and authenticated if the entity authentication scheme supports authentication.
payloadchunk = {
"#mandatory" : [ "payload", "signature" ],
"payload" : "binary",
"signature" : "binary"
}
Field | Description |
---|---|
payload | payload or ciphertext envelope containing the payload (payload) |
signature | verification data of the payload |
payload = {
"#mandatory" : [ "sequencenumber", "messageid", "data" ],
"sequencenumber" : "int64(1,2^53^)",
"messageid" : "int64(0,2^53^)",
"endofmsg" : "boolean",
"compressionalgo" : "enum(GZIP|LZW)",
"data" : "binary"
}
Field | Description |
---|---|
compressionalgo | compression algorithm used to compress the data |
data | optionally compressed application data |
endofmsg | indicates if this is the last payload chunk of the message |
messageid | message ID |
sequencenumber | chunk sequence number |
The sequence number identifies order of payload chunks. This is a monotonically increasing number that begins at 1 for the first payload chunk of a message and is incremented by one for each subsequent payload chunk of the same message.
The message ID binds the payload chunk to a specific message. If the payload chunk message ID does not match the MSL header message ID the payload chunk must be discarded.
If the end of message flag is true then this is the last payload chunk of the message.
The application data. If this is the last payload chunk of the message the data may be empty.
If a compression algorithm is specified then the application data has been compressed.
A Netflix Original Production
Tech Blog | Twitter @NetflixOSS | Jobs
- Introduction
- Encoding & Normalization
- Cryptography
- Versioning
- MSL Networks
- Entity Authentication
- User Authentication
- Key Exchange
- Service Tokens
- Messages
- Error Messages
- Application Security Requirements
- Protocol Implementation
- Configuration Guide