test\testrunner.jsand try out
npm testfor an example of seeing the client and server running through the full SRP6a protocol.
npm run-script buildconverts into a browserify module within the file
browser.js. See this article as an introduction to browserify.
UsingFor the definitions of the values discussed below please refer to the SRP design page. The following sequence diagram shows how to register a user with an SRP salt and verifier as demonstrated by the Thinbus Demo Application.
saltand with the salt, email and password generates an SRP
verififer. Only the email,
verifierare transmitted to the server and the generated values are saved into the database keyed by the email.
Note Always use browser developer tools to inspect what you actually post to the server and only post the values shown in the sequence diagram as defined in the SRP design page. It is a protocol violation and security bug if the raw password is accidently transmitted to the server even if it is ignored by the server. It is also a protocol violation and a security bug if you accidently transmit the verifier to the browser.
The following sequence diagram shows how to login a registered user.
saltand a one-time server challenge
B. Then client creates a one-time client challenge
Aand uses all the information to compute a password proof
M1. It then posts to the server the email,
M1as the users credentials. The server uses all the information (including a private part of the challenge to check the password proof). Only the email, client challenge
Aand the password proof
M1are transmitted to the server. Note that the server needs to hold the private challenge state
bthat corresponds to the public challenge
Bsent to the client. It can store this private state in a time limited cache.
There is an optional step
M2is the server's proof of a shared session key to the client. You can return
M2proof is an additional check of the authenticity of the server; it confirms to trusted client code that the server knows the verifier matching the user password.
Note that you don't have to use AJAX for SRP. It is used in the examples to hide the fact that with SRP you need an additional round-trip to the server to generate a challenge using the users verifier. You can avoid using AJAX by splitting the username and password fields across two pages. The first page can send the username and the next page can have a hidden fields containing the user specific salt and the server challenge
B. This simply replaces the AJAX trip with an explicit page load.
Note as per RFC 2945 the user ID (usually their email) is concatenated to their password when generating the verifier. This means that if a user changes either their email address or their password you need to generate a new verifier and replace the old one in the database.
Note always use browser developer tools to inspect what you actually post to the server and only post the values shown in the sequence diagram as defined in the SRP design page. It is a protocol violation and a security bug to accidently transmit to the server anything else even if it is ignored by the server.
Note that the server has to remember the private ephemeral key
bthat matches the public ephemeral key
Bsent as a one-time server challenge to the user. This requires storing
beither in the database, the server session or a server cache for the short duration of the login protocol. You cannot pass this value back to the server from the client without compromising security. The server should not use any values transmitted from the client other than those shown in the sequence diagram and named in the SRP design page.
Note if you want to use the shared session key for follow-on cryptography you should use
client.getSessionKey()to retrieved the session key from the thinbus object and destroy the thinbus object as discussed above. The typical way to do this is to put the session key into browser local session storage. Then you can unload the login page then load a main landing page that collects the session key from storage.
Creating A Custom Large Safe PrimeThe Java version of Thinbus has a command line tool and instructions how to use openssl to create safe prime see https://bitbucket.org/simonmassey/thinbus-srp-js/overview
- Use Thinbus SRP over HTTPS. Configure your webserver to mark session cookies as secure to prevent accidental use of HTTP. Configure HSTS to force HTTPS with your service. If your customers use a company supplied computer going via a corporate web proxy then HTTPS may be decrypted and monitored. HTTPS may be compromised due to things like bad certs in the wild. HTTPS may be compromised by bugs or misconfigurations such as Heartbleed. HTTPS alone cannot protected against leaking passwords into error messages in your webserver logs. SRP over HTTPS is much safer than either used alone.
- Use a custom large safe prime number
Nusing the instructions above. Tip: Check on the browsers and hardware you are targeting that the math runs fast enough for a good user experience for your chosen bit length.
- Make the salt column in the database
not nulland add a uniqueness constraint.
Use symmetric AES encryption with a key only visible at the webserver to encrypt the verifier
vvalue within the database. This protects against off-site database backups being used in an offline dictionary attack against
- You can prevent privileged accounts from logging in using legacy browsers by checking
random16byteHex.isWebCryptoAPI()when fetching the user salt; simply abort the protocol for privileged accounts when secure random numbers are not available at the browser. If you allow the use of browsers that don't have the
WebCryptoAPIsecure random number APIs then the fallback random generator hashes
window.cookieas part of the generator seed. Consider adding a secure random cookie to help seed the fallback generator.
- Don't include any JS files or any CSS files from external sites onto your login page.
- Count the number of failed password attempts and present the user with a CAPTCHA after a dozen attempts. This slows down scripted online dictionary attacks. Consider suspending the account (possibly temporarily) after a large number of contiguous failed attempts to defeat someone carefully researching a user then trying to guess their likely password.
MiscellaneousThe name Thinbus is a play on the name of the SRP Java library Nimbus. Thinbus NPM (this repo) is tested against Thinbus JavaSciprt taken from the Java version, which in turn is testing against Nimbus, which gives higher confidence in its correctneess. Nimbus has had a lot of eyes look at it over the years and was carefully check against other Java SRP library code and the example code provided by the inventor of SRP.
- pysrpthinbus is a fork of pysrp which is compatible with Thinbus so that you can use Python on the server.
Copyright 2014-2017 Simon Massey Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.