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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@xscale/hash

v1.0.1

Published

Framework agnostic Password hashing package with support for PHC string format

Downloads

9

Readme

Hash

The @xscale/hash package provides a platform-agnostic multi-driver hashing module that adheres to the PHC string format. It offers first-class support for popular algorithms like bcrypt, scrypt, and argon2, with the flexibility to add custom drivers.

Usage

The hash.make method accepts a plain text string (typically a user password) and returns a hashed output.

import { Hash, Scrypt } from '@xscale/hash'

const hash = new Hash(new Scrypt())

const hashed = await hash.make('user_password')

// $scrypt$n=16384,r=8,p=1$awRyvKyosNsLRGqXQnKs1w$ePrdivX50POaYJ18x5r1+fU7Bfc232KFeqku3U/vZVD62JQycLuAVRdlLkM/lkdQQFS+CT6j32422lm58BRB1A

You cannot convert a hash value to plain text, hashing is a one-way process, and there is no way to retrieve the original value after a hash has been generated.

However, hashing provides a way to verify if a given plain text value matches against an existing hash, and you can perform this check using the hash.verify method.

if (await hash.verify(hashed, 'user_password')) {
  // Password is correct
} else {
  // Password is incorrect
}

Configuration

You can configure the hash driver by passing an object to the constructor.

The default driver is set to scrypt because scrypt uses the Node.js native crypto module and does not require any third-party packages.

import { Hash, Scrypt } from '@xscale/hash'

const scryptHash = new Hash(new Scrypt())

Argon

Argon is the recommended hashing algorithm to hash user passwords. To use argon with the hash service, you must install the argon2 npm package.

yarn add argon2
import { Hash, Argon } from '@xscale/hash'

const argonHash = new Hash(new Argon({
    version: 0x13, // hex code for 19
    variant: 'id',
    iterations: 3,
    memory: 65536,
    parallelism: 4,
    saltSize: 16,
    hashLength: 32,
}))

variant

The argon hash variant to use.

  • d is faster and highly resistant against GPU attacks, which is useful for cryptocurrency
  • i is slower and resistant against tradeoff attacks, which is preferred for password hashing and key derivation.
  • id (default) is a hybrid combination of the above, resistant against GPU and tradeoff attacks.

version

The argon version to use. The available options are 0x10 (1.0) and 0x13 (1.3). The latest version should be used by default.


iterations

The iterations count increases the hash strength but takes more time to compute.

The default value is 3.


memory

The amount of memory to be used for hashing the value. Each parallel thread will have a memory pool of this size.

The default value is 65536 (KiB).


parallelism

The number of threads to use for computing the hash.

The default value is 4.


saltSize

The length of salt (in bytes). Argon generates a cryptographically secure random salt of this size when computing the hash.

The default and recommended value for password hashing is 16.


hashLength

Maximum length for the raw hash (in bytes). The output value will be longer than the mentioned hash length because the raw hash output is further encoded to PHC format.

The default value is 32

Bcrypt

yarn add bcrypt
import { Hash, Bcrypt } from '@xscale/hash'

const bcryptHash = new Hash(new Bcrypt({
    rounds: 10,
    saltSize: 16,
    version: '2b'
}))

rounds

The cost for computing the hash. We recommend reading the A Note on Rounds section from Bcrypt docs to learn how the rounds value has an impact on the time it takes to compute the hash.

The default value is 10.


saltSize

The length of salt (in bytes). When computing the hash, we generate a cryptographically secure random salt of this size.

The default value is 16.


version

The version for the hashing algorithm. The supported values are 2a and 2b. Using the latest version, i.e., 2b is recommended.

Scrypt

The scrypt driver uses the Node.js crypto module for computing the password hash. The configuration options are the same as those accepted by the Node.js scrypt method.

import { Hash, Scrypt } from '@xscale/hash'

const scryptHash = new Hash(new Scrypt({
  cost: 16384,
  blockSize: 8,
  parallelization: 1,
  saltSize: 16,
  maxMemory: 33554432,
  keyLength: 64
}))

Checking if a password needs to be rehashed

The latest configuration options are recommended to keep passwords secure, especially when a vulnerability is reported with an older version of the hashing algorithm.

After you update the config with the latest options, you can use the hash.needsReHash method to check if a password hash uses old options and perform a re-hash.

The check must be performed during user login because that is the only time you can access the plain text password.

if (await hash.needsReHash(hashed)) {
  const newHash = await hash.make('user_password')
  // Update the user password with the new hash
}

Creating a custom hash driver

A hash driver must implement the HashDriverContract interface. Also, the official Hash drivers use PHC format to serialize the hash output for storage. You can check the existing driver's implementation to see how they use the PHC formatter to make and verify hashes.

import {
  HashDriverContract,
} from '@xscale/hash'

/**
 * Config accepted by the hash driver
 */
export type PbkdfConfig = {
}

/**
 * Driver implementation
 */
export class Pbkdf2Driver implements HashDriverContract {
  constructor(public config: PbkdfConfig) {
  }

  /**
   * Check if the hash value is formatted as per
   * the hashing algorithm.
   */
  isValidHash(value: string): boolean {
  }

  /**
   * Convert raw value to Hash
   */
  async make(value: string): Promise<string> {
  }

  /**
   * Verify if the plain value matches the provided
   * hash
   */
  async verify(
    hashedValue: string,
    plainValue: string
  ): Promise<boolean> {
  }

  /**
   * Check if the hash needs to be re-hashed because
   * the config parameters have changed
   */
  needsReHash(value: string): boolean {
  }
}

In the above code example, we export the following values.

  • PbkdfConfig: TypeScript type for the configuration you want to accept.

  • Pbkdf2Driver: The class that implements the HashDriverContract interface.

Using the driver

Once you have created the driver, you can use it with the Hash service.

import { Hash } from '@xscale/hash'
import { Pbkdf2Driver } from 'path/to/driver'

const hash = new Hash(new Pbkdf2Driver({
  // Your config
}))

Vulnerability Reporting

If you discover a security vulnerability within this package, please report it to Github Security