npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@scirexs/srp6a

v1.0.1

Published

SRP-6a (Secure Remote Password) implementation in TypeScript for browser and server.

Readme

Package for SRP-6a Authentication

SRP-6a (Secure Remote Password) implementation in TypeScript for browser and server.

npm version JSR license

Installation

# npm
npm install @scirexs/srp6a

# JSR (Deno)
deno add jsr:@scirexs/srp6a

Usage

For Client

For details, see the client documentation.

Registration Phase

import { getDefaultConfig, createUserCredentials } from "@scirexs/srp6a/client";

const config = getDefaultConfig();
const credentials = await createUserCredentials(username, password, config);

// send data to server like `fetch(url, { method: "POST", body: JSON.stringify(credentials)});`

Authentication Phase

// the args type `CryptoSource` is defined as `bigint | string | Uint8Array | CryptoNumber;`.
import { getDefaultConfig, createLoginHello, createEvidence, verifyServer } from "@scirexs/srp6a/client";

const config = getDefaultConfig();
const [hello, pair] = createLoginHello(username, config);
// send hello to server like `fetch(url, { method: "POST", body: JSON.stringify(hello)});`

// receive `salt` and public key from the server
// if the server uses this package, you can use `extractServerHello(response)`
const [evidence, expected] = await createEvidence(username, password, salt, server, pair, config);
// send evidence to server like `fetch(url, { method: "POST", body: JSON.stringify(evidence)});`

// receive `result` and `serverEvidence` and more
// if the server uses this package, you can use `extractLoginResult(response)`
if (!result) throw new Error("Failed to login.");
if (!verifyServer(expected, serverEvidence)) throw new Error("Could not verify the server.");

For Server

For details, see the server documentation.

Authentication Phase

// the args type `CryptoSource` is defined as `bigint | string | Uint8Array | CryptoNumber;`.
import { getDefaultConfig, createServerHello, authenticate } from "@scirexs/srp6a/server";

// receive `username` and public key from the client
// if the client uses this package, you can use `extractClientHello(request)`

// read user's `salt` and `verifier` from the database
// if the user does not exist, use `createDummyHello` instead of `createServerHello`
const config = getDefaultConfig();
const [hello, pair] = await createServerHello(salt, verifier, config);
// it is recommended to always use `addRandomDelay` before sending hello to mitigate timing attacks
// response hello to client like `new Response(JSON.stringify(hello));`

// receive `username` and `evidence` from the client
// if the client uses this package, you can use `extractLoginEvidence(request)`
const result = await authenticate(username, salt, verifier, pair, client, evidence, config);
// add other data to the result object
// response result to client like `new Response(JSON.stringify(result));`

Encryption Configuration

SRP Group Parameters

GROUP_XXXX indicates "SRP Group Parameters" of RFC 5054 Appendix A.

import { SRPConfig, SHA_512, GROUP_4096 } from "@scirexs/srp6a/client";
// import { SRPConfig, SHA_512, GROUP_4096_FOR_SERVER } from "@scirexs/srp6a/server";

const config = new SRPConfig(GROUP_4096, SHA_512);
// const config = new SRPConfig(GROUP_4096_FOR_SERVER, SHA_512);

getDefaultConfig() returns new SRPConfig(GROUP_2048, SHA_256).

The difference between GROUP_4096 and GROUP_4096_FOR_SERVER is whether they include a precomputed multiplier value. GROUP_4096 does not include the precomputed multiplier to reduce package size, as it can be derived through calculation when needed.

Salt Length

The salt bytes should be greater than the hash output bytes, so we defined salt length as twice the output bytes. For example, it will be 64 bytes if use SHA-256 hash algorithm.

Warning

This package includes security countermeasures such as constant-time comparisons and random delay insertion. However, it has never received an independent third-party security audit for correctness and security.

Do not use this package in production environments without understanding the security risks involved. USE AT YOUR OWN RISK!

SRP Overview

Procedure

Signup

  1. Client: Calculate salt, verifier from username and password (createUserCredentials)
  2. Client: Send Username, salt, verifier
  3. Server: Store them

Login

  1. Client: Generate random key pair (createLoginHello)
  2. Client: Send Username, public key of the pair
  3. Server: Read stored data including salt, verifier
  4. Server: Generate random key pair (createServerHello)
  5. Server: Send salt, public key of the pair
  6. Client: Calculate session key (createEvidence includes step 6-8)
  7. Client: Calculate client evidence from session key
  8. Client: Calculate expected server evidence
  9. Client: Send the client evidence
  10. Server: Calculate session key (authenticate includes step 10-13)
  11. Server: Calculate client evidence from session key
  12. Server: Confirm exactly matched evidences
  13. Server: Calculate server evidence from client evidence and session key
  14. Server: Send server evidence and result of authentication
  15. Client: Confirm exactly matched the server evidences and expected (verifyServer)

Vocabulary

Operator, Function

|Expression|Description| |---|---| |||Concatenate| |^|(Modular) Exponentiation| |H()|One-way hash function| |RAND()|Generate secure random array of bytes| |MP(n,k,m)|Calculates modPow as n^k % m| |PAD(d)|Cast d to zero-padding|

Variable

|Variable|Description| |---|---| |N|A large safe prime| |g|A generator modulo N| |k|Multiplier parameter| |s|User's salt| |U|Username| |p|Cleartext Password| |I|Identity hash derived from U and p| |u|Random scrambling parameter| |a,b|Secret ephemeral values| |A,B|Public ephemeral values| |x|Private key derived from password| |v|Password verifier| |S|Session key| |K|Strong session key| |Mc,Ms|Evidence|

Name in Code

|Variable|Name| |---|---| |N|prime| |g|generator| |k|multiplier| |s|salt| |U|username| |p|password| |I|identity| |x|secret| |u|scrambling| |a|pair.private, pvt| |A|pair.public, pub, client| |b|pair.private, pvt| |B|pair.public, pub, server| |v|verifier| |S|session| |K|key| |Mc,Ms|evidence|

Formula for each variable

|Variable|Expression|Note| |---|---|---| |N||-| |g||-| |U||-| |p||-| |I|H(U | ":" | p)|-| |x|H(s | I)|-| |s|RAND()|-| |v|MP(g, x, N)|-| |k|H(N | PAD(g))|-| |a|RAND()|-| |A|MP(g, a, N)|-| |b|RAND()|-| |B|k * v + MP(g, b, N)|-| |u|H(PAD(A) | PAD(B))|-| |Sc|MP(B - (k * MP(g, x, N)), a + (u * x), N)|Client side| |Ss|MP(MP(v, u, N) * A, b, N)|Server side| |Kc|H(Sc)|Client side| |Ks|H(Ss)|Server side| |Mc|H(H(N) xor H(g), H(U), s, A, B, Kc)|-| |Mc'|H(H(N) xor H(g), H(U), s, A, B, Ks)|Verify Mc| |Ms|H(A, Mc, Ks)|-| |Ms'|H(A, Mc, Ks)|Expected Ms|

SRP Details

Signup phase (Client)

  1. Client: Send U,s,v.

|Variable|Expression| |---|---| |N,g|<read from constant>| |U,p|<read from user>| |s|RAND()| |I|H(U | ":" | p)| |x|H(s | I)| |v|MP(g, x, N)|

Login phase

  1. Client: Send U,A.

|Variable|Expression| |---|---| |N,g|<read from constant>| |U|<read from user>| |a|RAND()| |A|MP(g, a, N)|

  1. Server: Send B,s.

|Variable|Expression| |---|---| |U,A|<read from client>| |N,g,s,v|<read from password file>| |b|RAND()| |k|H(N | PAD(g))| |B|k * v + MP(g, b, N)|

  1. Client: Expect Ms and send Mc.

|Variable|Expression| |---|---| |U,a,A|<read from state>| |s,B|<read from server>| |p|<read from user>| |I|H(U | ":" | p)| |x|H(s | I)| |u|H(PAD(A) | PAD(B))| |k|H(N | PAD(g))| |Sc|MP(B - (k * MP(g, x, N)), a + (u * x), N)| |Kc|H(Sc)| |Mc|H(H(N) xor H(g), H(U), s, A, B, Kc)| |Ms'|H(A, Mc, Kc)|

  1. Server: Verify Mc and Send Ms

|Variable|Expression| |---|---| |N,g,U,s,v,A,b,B|<read from state>| |Mc|<read from client>| |u|H(PAD(A) | PAD(B))| |Ss|MP(MP(v, u, N) * A, b, N)| |Ks|H(Ss)| |Mc'|H(H(N) xor H(g), H(U), s, A, B, Ks)| |Ms|H(A, Mc, Ks)|

  1. Client: Verify Ms

|Variable|Expression| |---|---| |Ms'|<read from state>| |Ms|<read from server>|