Difference between revisions of "SASL Authentication and SCRAM"
Neustradamus (talk | contribs) m |
Neustradamus (talk | contribs) m |
||
Line 1: | Line 1: | ||
[https://tools.ietf.org/html/rfc5802 SCRAM-SHA-1] is a SASL mechanism improving on [[ | [https://tools.ietf.org/html/rfc5802 Salted Challenge Response Authentication Mechanism (SCRAM) SASL and GSS-API Mechanisms (SCRAM-SHA-1(-PLUS)] is a SASL mechanism improving on [[SASL and DIGEST-MD5|DIGEST-MD5]] ([https://tools.ietf.org/html/rfc6331 RFC6331: Moving DIGEST-MD5 to Historic]). | ||
Its main benefits are in offering both a method to salt and hash the password in storage and in transit. This page aims to give a short introduction on how to implement it in a client. | |||
== Overview == | In [https://tools.ietf.org/html/rfc8600 RFC8600: Using Extensible Messaging and Presence Protocol (XMPP) for Security Information Exchange]: | ||
"When using the SASL SCRAM mechanism, the SCRAM-SHA-256-PLUS variant SHOULD be preferred over the SCRAM-SHA-256 variant, and SHA-256 variants [RFC7677] SHOULD be preferred over SHA-1 variants [RFC5802]". | |||
<span style="color:#FF0000">Please note that there is now [https://tools.ietf.org/html/rfc7677 RFC7677: SCRAM-SHA-256 and SCRAM-SHA-256-PLUS Simple Authentication and Security Layer (SASL) Mechanisms], already integrated by several XMPP software servers (Isode M-Link, Jackal, Metronome, Prosody 0.12.x, Tigase 8.0) and several XMPP sotware clients (Conversations, Gajim 1.2.0-dev, KDE Kaidan, Psi/Psi+, Tigase Beagle IM, Tigase Siskin IM, Tigase Stork IM, UWPX).</span> | |||
== SCRAM-SHA-1(-PLUS) == | |||
=== Overview === | |||
The basic overview of how this mechanism works is: | The basic overview of how this mechanism works is: | ||
Line 16: | Line 22: | ||
The cryptographic algorithms needed are [https://tools.ietf.org/html/rfc3174 SHA-1], [https://tools.ietf.org/html/rfc2104 HMAC] with SHA-1 and [https://tools.ietf.org/html/rfc2898 PBKDF2] with SHA-1. It is advised to find libraries to use these algorithms instead of implementing them from scratch. | The cryptographic algorithms needed are [https://tools.ietf.org/html/rfc3174 SHA-1], [https://tools.ietf.org/html/rfc2104 HMAC] with SHA-1 and [https://tools.ietf.org/html/rfc2898 PBKDF2] with SHA-1. It is advised to find libraries to use these algorithms instead of implementing them from scratch. | ||
== In detail == | === In detail === | ||
<ol> | <ol> | ||
Line 104: | Line 110: | ||
</ol> | </ol> | ||
== Extras == | === Extras === | ||
This is the basic version of the algorithm. You can extend it to do: | This is the basic version of the algorithm. You can extend it to do: | ||
Line 110: | Line 116: | ||
* Channel binding. This mixes in some information from the TLS connection to the procedure to prevent MitM attacks. | * Channel binding. This mixes in some information from the TLS connection to the procedure to prevent MitM attacks. | ||
* Hashed storage. If the server always sends the same salt and i values, then the client can store only <code>clientKey</code>, instead of the user's password. This is more secure (as the client doesn't need to store the password, just a hard to reverse salt) and faster, as the client doesn't need to do all the hashing every time. | * Hashed storage. If the server always sends the same salt and i values, then the client can store only <code>clientKey</code>, instead of the user's password. This is more secure (as the client doesn't need to store the password, just a hard to reverse salt) and faster, as the client doesn't need to do all the hashing every time. | ||
== Common pitfalls == | === Common pitfalls === | ||
* Don't assume anything about the length of the nonces or salt (though if you generate them, make sure they are long enough and cryptographically random). | * Don't assume anything about the length of the nonces or salt (though if you generate them, make sure they are long enough and cryptographically random). | ||
Line 119: | Line 124: | ||
* The <code>initialMessage</code> part of the <code>authMessage</code> does not include the GS2 header (in most situations, this is <code>"n,,"</code>). | * The <code>initialMessage</code> part of the <code>authMessage</code> does not include the GS2 header (in most situations, this is <code>"n,,"</code>). | ||
== Test vectors == | === Test vectors === | ||
Here is a complete example: | Here is a complete example: | ||
Line 160: | Line 165: | ||
Server's server signature (hex): <code>ae617da6a57c4bbb2e0286568dae1d251905b0a4</code> | Server's server signature (hex): <code>ae617da6a57c4bbb2e0286568dae1d251905b0a4</code> | ||
== SCRAM-SHA-256(-PLUS) == | |||
Possibly, also adding [https://tools.ietf.org/html/rfc7677 RFC7677: SCRAM-SHA-256 and SCRAM-SHA-256-PLUS Simple Authentication and Security Layer (SASL) Mechanisms]. | |||
It is supported by several XMPP software servers (Isode M-Link, Jackal, Metronome, Prosody 0.12.x, Tigase 8.0) and several XMPP sotware clients (Conversations, Gajim 1.2.0-dev, KDE Kaidan, Psi/Psi+, Tigase Beagle IM, Tigase Siskin IM, Tigase Stork IM, UWPX). | |||
== Channel Bindings == | |||
- [https://tools.ietf.org/html/rfc5056 RFC5056: On the Use of Channel Bindings to Secure Channels] | |||
- [https://tools.ietf.org/html/rfc5929 RFC5929: Channel Bindings for TLS] | |||
- [https://www.iana.org/assignments/channel-binding-types/channel-binding-types.xhtml Channel-Binding Types] | |||
== IANA == | |||
- [https://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml Simple Authentication and Security Layer (SASL) Mechanisms] | |||
== LDAP == | |||
- [https://tools.ietf.org/html/rfc5803 RFC5803: Lightweight Directory Access Protocol (LDAP) Schema for Storing Salted: Challenge Response Authentication Mechanism (SCRAM) Secrets] | |||
== HTTP == | |||
- [https://tools.ietf.org/html/rfc7804 RFC7804: Salted Challenge Response HTTP Authentication Mechanism] |
Revision as of 15:40, 13 November 2019
Salted Challenge Response Authentication Mechanism (SCRAM) SASL and GSS-API Mechanisms (SCRAM-SHA-1(-PLUS) is a SASL mechanism improving on DIGEST-MD5 (RFC6331: Moving DIGEST-MD5 to Historic).
Its main benefits are in offering both a method to salt and hash the password in storage and in transit. This page aims to give a short introduction on how to implement it in a client.
In RFC8600: Using Extensible Messaging and Presence Protocol (XMPP) for Security Information Exchange:
"When using the SASL SCRAM mechanism, the SCRAM-SHA-256-PLUS variant SHOULD be preferred over the SCRAM-SHA-256 variant, and SHA-256 variants [RFC7677] SHOULD be preferred over SHA-1 variants [RFC5802]".
Please note that there is now RFC7677: SCRAM-SHA-256 and SCRAM-SHA-256-PLUS Simple Authentication and Security Layer (SASL) Mechanisms, already integrated by several XMPP software servers (Isode M-Link, Jackal, Metronome, Prosody 0.12.x, Tigase 8.0) and several XMPP sotware clients (Conversations, Gajim 1.2.0-dev, KDE Kaidan, Psi/Psi+, Tigase Beagle IM, Tigase Siskin IM, Tigase Stork IM, UWPX).
SCRAM-SHA-1(-PLUS)
Overview
The basic overview of how this mechanism works is:
- The client sends the username it wants to authenticate as.
- The server sends back the salt for that user and the number of iterations (either by generating them or looking them up in its database for the given username).
- The client hashes the password with the given salt for the given number of iterations.
- The client sends the result back.
- The server does a variation of the hashing and sends it result back to the client, so the client can also verify that the server had the password/a hash of the password.
The cryptographic algorithms needed are SHA-1, HMAC with SHA-1 and PBKDF2 with SHA-1. It is advised to find libraries to use these algorithms instead of implementing them from scratch.
In detail
- First normalize the password (using SASLprep), this will be
normalizedPassword
. This is to ensure the UTF8 encoding can't contain variations of the same password. - Pick a random string (for example 32 hex encoded bytes). This will be
clientNonce
. - The initialMessage is:
"n=" .. username .. ",r=" .. clientNonce
- The client prepends the GS2 header (
"n,,"
) to the initialMessage and base64-encodes the result. It sends this as its first message:<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="SCRAM-SHA-1"> biwsbj1yb21lbyxyPTZkNDQyYjVkOWU1MWE3NDBmMzY5ZTNkY2VjZjMxNzhl </auth>
- The server responds with a challenge. The data of the challenge is base64 encoded:
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl"> cj02ZDQ0MmI1ZDllNTFhNzQwZjM2OWUzZGNlY2YzMTc4ZWMxMmIzOTg1YmJkNGE4ZTZmODE0YjQyMmFiNzY2NTczLHM9UVNYQ1IrUTZzZWs4YmY5MixpPTQwOTY= </challenge>
- The client base64 decodes it:
r=6d442b5d9e51a740f369e3dcecf3178ec12b3985bbd4a8e6f814b422ab766573,s=QSXCR+Q6sek8bf92,i=4096
- The client parses this:
- r = This is the serverNonce. The client MUST ensure that it starts with the clientNonce it sent in its initial message.
- s = This is the salt, base64 encoded (yes, this is base64-encoded twice!)
- i = This is the number of iterations, i.
- The client computes:
clientFinalMessageBare = "c=biws,r=" .. serverNonce saltedPassword = PBKDF2-SHA-1(normalizedPassword, salt, i) clientKey = HMAC-SHA-1(saltedPassword, "Client Key") storedKey = SHA-1(clientKey) authMessage = initialMessage .. "," .. serverFirstMessage .. "," .. clientFinalMessageBare clientSignature = HMAC-SHA-1(storedKey, authMessage) clientProof = clientKey XOR clientSignature serverKey = HMAC-SHA-1(saltedPassword, "Server Key") serverSignature = HMAC-SHA-1(serverKey, authMessage) clientFinalMessage = clientFinalMessageBare .. ",p=" .. base64(clientProof)
- The client base64 encodes the
clientFinalMessage
and sends it as a response:<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl"> Yz1iaXdzLHI9NmQ0NDJiNWQ5ZTUxYTc0MGYzNjllM2RjZWNmMzE3OGVjMTJiMzk4NWJiZDRhOGU2ZjgxNGI0MjJhYjc2NjU3MyxwPXlxbTcyWWxmc2hFTmpQUjFYeGFucG5IUVA4bz0= </response>
-
If everything went well, you'll get a
<success>
response from the server:<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> dj1wTk5ERlZFUXh1WHhDb1NFaVc4R0VaKzFSU289 </success>
Base64 decoded this contains:
v=pNNDFVEQxuXxCoSEiW8GEZ+1RSo=
- The client MUST make sure the value of v is the base64 encoding of the
serverSignature
(yes, this value is also base64-encoded twice).
Extras
This is the basic version of the algorithm. You can extend it to do:
- Channel binding. This mixes in some information from the TLS connection to the procedure to prevent MitM attacks.
- Hashed storage. If the server always sends the same salt and i values, then the client can store only
clientKey
, instead of the user's password. This is more secure (as the client doesn't need to store the password, just a hard to reverse salt) and faster, as the client doesn't need to do all the hashing every time.
Common pitfalls
- Don't assume anything about the length of the nonces or salt (though if you generate them, make sure they are long enough and cryptographically random).
- The salt is base64 encoded and can contain any data (embedded NULs).
- Not using SASLprep may work fine for people using ASCII passwords, but it may completely break logging in for people using other scripts.
- The
initialMessage
part of theauthMessage
does not include the GS2 header (in most situations, this is"n,,"
).
Test vectors
Here is a complete example:
Username: user
Password: pencil
Client generates the random nonce fyko+d2lbbFgONRv9qkxdawL
Initial message: n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL
Server generates the random nonce 3rfcNHYJY1ZVvWVs7j
Server replies: r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096
The salt (hex): 4125c247e43ab1e93c6dff76
Client final message bare: c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
Salted password (hex): 1d96ee3a529b5a5f9e47c01f229a2cb8a6e15f7d
Client key (hex): e234c47bf6c36696dd6d852b99aaa2ba26555728
Stored key (hex): e9d94660c39d65c38fbad91c358f14da0eef2bd6
Auth message: n=user,r=fyko+d2lbbFgONRv9qkxdawL,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096,c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j
Client signature (hex): 5d7138c486b0bfabdf49e3e2da8bd6e5c79db613
Client proof (hex): bf45fcbf7073d93d022466c94321745fe1c8e13b
Server key (hex): 0fe09258b3ac852ba502cc62ba903eaacdbf7d31
Server signature (hex): ae617da6a57c4bbb2e0286568dae1d251905b0a4
Client final message: c=biws,r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,p=v0X8v3Bz2T0CJGbJQyF0X+HI4Ts=
Server final message: v=rmF9pqV8S7suAoZWja4dJRkFsKQ=
Server's server signature (hex): ae617da6a57c4bbb2e0286568dae1d251905b0a4
SCRAM-SHA-256(-PLUS)
Possibly, also adding RFC7677: SCRAM-SHA-256 and SCRAM-SHA-256-PLUS Simple Authentication and Security Layer (SASL) Mechanisms.
It is supported by several XMPP software servers (Isode M-Link, Jackal, Metronome, Prosody 0.12.x, Tigase 8.0) and several XMPP sotware clients (Conversations, Gajim 1.2.0-dev, KDE Kaidan, Psi/Psi+, Tigase Beagle IM, Tigase Siskin IM, Tigase Stork IM, UWPX).
Channel Bindings
- RFC5056: On the Use of Channel Bindings to Secure Channels
- RFC5929: Channel Bindings for TLS
IANA
- Simple Authentication and Security Layer (SASL) Mechanisms
LDAP
HTTP
- RFC7804: Salted Challenge Response HTTP Authentication Mechanism