Modular implementation of Secure Remote Password protocol for NodeJS/Browser/React Native environments. This library is inspired by NaCl crypto library and tries to provide same safety and simplicity to the user.
This library is a little bit opioniated about how pefrom authentication process i believe that this process covers all cases and if it doesn't match your project, please, open an issue an i will implement an alternative way or suggest work-around.
- 💪Secure default settings
- 🚀Fast and Safe SRP Engine that conforms to RFC 5054
- 🦺SRP Server and Client that is safe to use without need of a deep knowledge of SRP
- 🧐Customizations for password hashing and proof calculation
yarn add srp6a
To use this library you have to configure SRP parameters. For simplicity you can use the default parameters:
import { SRP } from 'srp6a';
import crypto from 'crypto';
const srp = new SRP('default');
For each user you have to generate random salt and store it in the database. Salt is not secret and could be treated the same way as a username.
const username = 'ex3ndr';
const password = '12345678';
const salt = srp.generateSalt();
const verifier = srp.computeVerifier(username, password, salt);
For authentication there are 'SRPClient' and 'SRPServer' classes. Beware: they can't be reused!. After failed or successful negotiation any function call will result in exception being thrown. If any function returns false then 'SRPClient'/'SRPServer' will turn into failed state and will not be usable anymore. You will have to start new authentication session.
const srpClient = new SRPClient('default');
const srpServer = new SRPServer('default');
First step is setting credentials on client and on server sides:
if (!client.setCredentials(username, password, salt)) {
throw Error('Unable to set client credentials');
}
if (!server.setCredentials(username, verifier, salt)) {
throw Error('Unable to set server credentials');
}
After setting credentials new ephemeral keys are generated, and they became available in publicKey
property. This property will throw an error if you haven't set credentials.
if (!client.setServerKey(server.publicKey)) {
throw Error('Unable to set server public key');
}
if (!server.setClientKey(client.publicKey)) {
throw Error('Unable to set client public key');
}
To get an acccess to Session Key you have to validate proofs. Server-side proof is not available until you have successfully validated client one.
if (!server.validateProof(client.proof)) {
throw Error('Invalid client proof');
}
if (!client.validateProof(server.proof)) {
throw Error('Invalid server proof');
}
After validation you can retreive session key:
const sessionKey = client.sessionKey;
const sessionKey = server.sessionKey;
There are some built-in presets (please, make a PR for some other well-established parameters). To use a preset simply provide a name to SRP/SRPClient/SRPServer constructors as a first parameter.
'default'
- Default safe parameters: 2048 bit group from RFC 5054 and SHA-256 for hashing.'homekit'
- HomeKit Accessory Protocol parameters: 3072 bit group from RFC 5054 and SHA-512 for hashing.
If the presets does not work for you, you can specify group and hashing algorithm manually:
{ group: GROUP, hash: HASH }
Where GROUP
could be one of:
- RFC 5054 groups:
- 1024 bit:
'rfc5054_1024'
- 1536 bit:
'rfc5054_1536'
- 2048 bit:
'rfc5054_2048'
- 3072 bit:
'rfc5054_3072'
- 4096 bit:
'rfc5054_4096'
- 6144 bit:
'rfc5054_6144'
- 8192 bit:
'rfc5054_8192'
- 1024 bit:
- Custom Group:
{ N: string, g: string }
. Both numbers are in HEX format with any number of space symbols and formatting. WhereHASH
could be one of: - Built-in hashing:
- SHA-1:
'sha-1'
- SHA-256:
'sha-256'
- SHA-512:
'sha-512'
- SHA-1:
- Custom hashing function of type:
(...src: (Buffer)[]) => Buffer