This document describes a password-based mutual authentication protocol. It provides a way for both the client and the server to authenticate each other and the protocol is relatively simple to implement.
- SCRAM: SCRAM is a similar protocol but it is a bit more complex. It conforms to both the SASL and the GSS-API standards which adds extra complexity and limitations on implementations. SCRAM also authenticates the client first and then authenticates the server whereas SPBMAP authenticates the server first and then the client. The authentication step is also a bit longer for SCRAM than for SPBMAP with 4 messages as compared to 3.
Strengths:
- The client never has to share their password with the server.
Limitations:
- The client sends a hash of their password to the server during registration.
- The client sends a truncated hash of their password to the server during authentication.
- The server sends a hash of the password to any client providing the correct truncated hash.
Possible attacks:
- A malicious server would during registration receive a hash of the password. Using this value, one could perform a dictionary or brute-force attack to try and find the original password. A strong password in combination with a strong client-side hash function makes this attack infeasible.
- A malicious server would during authentication receive a truncated hash of the password. This value enables the same types of attacks as in point number 1, except that the attacker could only hope to narrow down the list of possible passwords and would not be able to figure out the correct password from this value alone.
- A malicious client could guess the correct truncated hash and would then receive a hash of the password. The chance of correctly guessing the correct truncated hash value is one in 2^20, which is roughly one in a million. Correctly guessing this value and receiving a server-side hash of the password enables the same types of attacks as in point number 1, except that the server-side hash function has also been used to produce the value which slows down the attacker further.
This section provides a rough outline of how this protocol functions. The sections Definitions and Specification describes the protocol in further detail.
The registration step consists of only one message: a request from the client.
- The client calculates a hash of their password and then sends their id and the password hash to the server.
Depiction of the information flow:
Client Server
------------------------------------------------
registration request
------------------------->
-------------------------------------------------
The authentication step consists of three messages: a request from the client, a response from the server that establishes mutual challenges and provides the server response to this challenge, and lastly a response to this challenge from the client.
- The client calculates the hash of their password and generates a challenge nonce. The client calculates a truncated signature of their password hash. The client then sends their id, truncated signature, and the nonce to the server.
- The server generates a challenge nonce and calculates its response to the mutual challenge. The server then sends the nonce, its challenge response, and the server side hashing parameters to the client.
- The client calculates the server side hash of the password and uses it to calculate its response to the mutual challenge. The client then sends its challenge response to the server.
When the server challenge response has been received by the client, they make sure that it matches the expected value. If it does, the server is authenticated. The server authenticates the client in the same way when it receives the client challenge response.
Depiction of the information flow:
Client Server
------------------------------------------------
challenge request
------------------------->
authentication response
<-------------------------
challenge response
------------------------->
-------------------------------------------------
There are a number of functions and values used in this protocol. These are defined in this section.
H_client
: The hash function used by the client.H_server
: The hash function used by the server.HMAC
: The HMAC-SHA-256 algorithm.
id
: The client identifier.password
: The client password.client_salt
: The salt used by the client.server_salt
: The salt used by the server.client_nonce
: Nonce generated by the client.server_nonce
: Nonce generated by the server.client_timestamp
: Timestamp generated by the client.
client_key := H_client(password,client_salt)
short_client_key := HMAC(client_key,id) % 220
short_client_signature := HMAC(short_client_key,"client"+client_nonce+"timestamp"+client_timestamp)
server_key := H_server(client_key,server_salt)
client_signature := HMAC(server_key,"client"+client_nonce+"server"+server_nonce)
server_signature := HMAC(server_key,"server"+server_nonce+"client"+client_nonce)
- All byte string values are encoded as hexadecimal strings.
- Text string values are first encoded in UTF-8 and integers are encoded as big-endian.
- If a byte string is shorter than 32 bytes, the string is prefixed with zeroes to make it 32 bytes long.
- If a byte string is longer than 32 bytes, the SHA-256 digest of the UTF-8 encoded string is used instead.
- Message parameters are sent as JSON using the field names as defined in this document.
- Example 1:
123 => "0x000000000000000000000000000000000000000000000000000000000000007b"
. - Example 2:
"abc" => "0x0000000000000000000000000000000000000000000000000000000000616263"
. - Example 3:
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" => "0x3964294b664613798d1a477eb8ad02118b48d0c5738c427613202f2ed123b5f1"
.
This section describes the communication between the server and the client in further detail.
Before the registration step, the client has id
, password
, client_salt
, H_client
and H_server
. The server has H_server
.
The registration proceeds as follows:
- The client calculates
client_key
. - The client sends
id
andclient_key
to the server. - The server asserts that
id
is not already registered in the database. - The server generates
server_salt
. - The server calculates
server_key
andshort_client_key
. - The server stores
id
,server_key
,short_client_key
, andserver_salt
.
Registration can fail at step 3 causing error A.
Before the authentication step, the client has id
, password
, client_salt
, H_client
and H_server
. The server has id
, server_id_salt
, server_salt
, H_server
, hashed_client_key
, and hashed_server_key
.
The registration proceeds as follows:
- The client generates
client_nonce
andclient_timestamp
. - The client calculates
short_client_signature
. - The client sends
id
,client_nonce
,client_timestamp
, andshort_client_signature
to the server. - The server calculates
short_client_signature
. - The server asserts that
id
is registered in the database, thatclient_timestamp
is larger than any previously used value, and thatshort_client_signature
matches the expected value. - The server generates
server_nonce
. - The server calculates
server_signature
. - The server sends
server_salt
,server_nonce
, andserver_signature
to the client. - The client calculates
server_key
,client_signature
, andserver_signature
. - The client asserts that
server_signature
matches the expected value. - The client sends
client_signature
to the server. - The server calculates
client_signature
. - The server asserts that
client_signature
matches the expected value.
Authentication can fail at step 5 causing error B, step 10 causing error C, or step 13 causing error D.
This section describes how registration and authentication errors should be handled.
- Error A: The server responds with the same message as for a successful request.
- Error B: The server responds in a way indistinguishable from the response to a successful
request, with incorrect
server_salt
andserver_signature
instead of the correct values. The incorrect server signature should be randomly generated. The incorrect salt must be unique but consistent for the inputs, i.e. every call with anid
andclient_key
must yield a differentserver_salt
from calls with any otherid
orclient_key
but the sameserver_salt
as previous and subsequent calls with the sameid
andclient_key
. - Error C: The client aborts the connection.
- Error D: The server aborts the connection.
Some points to consider when implementing this protocol are:
H_client
andH_server
should be secure hash functions, for example Scrypt or Argon2 with good settings.- Both
client_salt
andserver_salt
should be unique to the user and the application.
This section lists some test vectors for this protocol.
Parameters:
H_client(msg,salt) := HMAC(msg,HMAC(salt,"client"))
H_server(msg,salt) := HMAC(msg,HMAC(salt,"server"))
id := "user"
password := "password"
client_salt := "client_salt"
server_salt := "server_salt"
client_nonce := "client_nonce"
server_nonce := "server_nonce"
client_timestamp := 123
Derived values:
client_key = 0xe9e46e87050e8bbd4d5c253cf422a2dce08d3f6435128a5fb85cf46a70b329fd
short_client_key = 0x791c3
short_client_signature = 0x7ead6
server_key = 0x83c5e50916f55b95efa47043142331f89b1832e6c5f878b220679008df73a49f
client_signature = 0xebba3659e3f3c5975b7e0660278fa280ff1f50f8f7bb30b30cc116243c8dc559
server_signature = 0x4721aaa93f334388fcfc9c5e22e91f3e201eecd4da64c2d28b343d6e81059196