Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/LinusU/secure-remote-password
A modern SRP implementation for Node.js and Web Browsers
https://github.com/LinusU/secure-remote-password
Last synced: about 2 months ago
JSON representation
A modern SRP implementation for Node.js and Web Browsers
- Host: GitHub
- URL: https://github.com/LinusU/secure-remote-password
- Owner: LinusU
- Created: 2017-09-08T10:14:59.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2022-10-26T11:47:51.000Z (almost 2 years ago)
- Last Synced: 2024-04-14T15:18:28.767Z (5 months ago)
- Language: JavaScript
- Size: 90.8 KB
- Stars: 97
- Watchers: 9
- Forks: 20
- Open Issues: 16
-
Metadata Files:
- Readme: readme.md
Awesome Lists containing this project
README
# Secure Remote Password for JavaScript
A modern [SRP](http://srp.stanford.edu) implementation for Node.js and Web Browsers.
## Installation
```sh
npm install --save secure-remote-password
```## Usage
### Signing up
When creating an account with the server, the client will provide a salt and a verifier for the server to store. They are calculated by the client as follows:
```js
const srp = require('secure-remote-password/client')// These should come from the user signing up
const username = '[email protected]'
const password = '$uper$ecure'const salt = srp.generateSalt()
const privateKey = srp.derivePrivateKey(salt, username, password)
const verifier = srp.deriveVerifier(privateKey)console.log(salt)
//=> FB95867E...console.log(verifier)
//=> 9392093F...// Send `username`, `salt` and `verifier` to the server
```*note:* `derivePrivateKey` is provided for completeness with the SRP 6a specification. It is however recommended to use some form of "slow hashing", like [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2), to reduce the viability of a brute force attack against the verifier.
### Logging in
Authenticating with the server involves mutliple steps.
**1** - The client generates a secret/public ephemeral value pair.
```js
const srp = require('secure-remote-password/client')// This should come from the user logging in
const username = '[email protected]'const clientEphemeral = srp.generateEphemeral()
console.log(clientEphemeral.public)
//=> DE63C51E...// Send `username` and `clientEphemeral.public` to the server
```**2** - The server receives the client's public ephemeral value and username. Using the username we retrieve the `salt` and `verifier` from our user database. We then generate our own ephemeral value pair.
*note:* if no user can be found in the database, a bogus salt and ephemeral value should be returned, to avoid leaking which users have signed up
```js
const srp = require('secure-remote-password/server')// This should come from the user database
const salt = 'FB95867E...'
const verifier = '9392093F...'const serverEphemeral = srp.generateEphemeral(verifier)
console.log(serverEphemeral.public)
//=> DA084F5C...// Store `serverEphemeral.secret` for later use
// Send `salt` and `serverEphemeral.public` to the client
```**3** - The client can now derive the shared strong session key, and a proof of it to provide to the server.
```js
const srp = require('secure-remote-password/client')// This should come from the user logging in
const password = '$uper$ecret'const privateKey = srp.derivePrivateKey(salt, username, password)
const clientSession = srp.deriveSession(clientEphemeral.secret, serverPublicEphemeral, salt, username, privateKey)console.log(clientSession.key)
//=> 2A6FF04E...console.log(clientSession.proof)
//=> 6F8F4AC3// Send `clientSession.proof` to the server
```**4** - The server is also ready to derive the shared strong session key, and can verify that the client has the same key using the provided proof.
```js
const srp = require('secure-remote-password/server')// Previously stored `serverEphemeral.secret`
const serverSecretEphemeral = '784D6E83...'const serverSession = srp.deriveSession(serverSecretEphemeral, clientPublicEphemeral, salt, username, verifier, clientSessionProof)
console.log(serverSession.key)
//=> 2A6FF04E...console.log(serverSession.proof)
//=> 92561B95// Send `serverSession.proof` to the client
```**5** - Finally, the client can verify that the server have derived the correct strong session key, using the proof that the server sent back.
```js
const srp = require('secure-remote-password/client')srp.verifySession(clientEphemeral.public, clientSession, serverSessionProof)
// All done!
```## API
### `Client`
```js
const Client = require('secure-remote-password/client')
```#### `Client.generateSalt() => string`
Generate a salt suitable for computing the verifier with.
#### `Client.derivePrivateKey(salt, username, password) => string`
Derives a private key suitable for computing the verifier with.
#### `Client.deriveVerifier(privateKey) => string`
Derive a verifier to be stored for subsequent authentication atempts.
#### `Client.generateEphemeral() => { secret: string, public: string }`
Generate ephemeral values used to initiate an authentication session.
#### `Client.deriveSession(clientSecretEphemeral, serverPublicEphemeral, salt, username, privateKey) => { key: string, proof: string }`
Comptue a session key and proof. The proof is to be sent to the server for verification.
#### `Client.verifySession(clientPublicEphemeral, clientSession, serverSessionProof) => void`
Verifies the server provided session proof. Throws an error if the session proof is invalid.
### `Server`
```js
const Server = require('secure-remote-password/server')
```#### `generateEphemeral(verifier)`
Generate ephemeral values used to continue an authentication session.
#### `deriveSession(serverSecretEphemeral, clientPublicEphemeral, salt, username, verifier, clientSessionProof)`
Comptue a session key and proof. The proof is to be sent to the client for verification.
Throws an error if the session proof from the client is invalid.