Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

argon2-pass

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

argon2-pass - npm Package Compare versions

Comparing version 0.1.3 to 0.2.0

dist/__tests__/base64.d.ts

33

CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 0.1.3
## [0.2.0] - 2018-09-08
### Added
- Added JSDoc comments to all functions and important objects. This was then used with the TypeDoc module to generate a documentation site for the package.
- Added synchronous versions of hash and verify. `hashPasswordSync()` and `verifyHashSync()`.
- Added get and set functions for MemLimit. `MemLimit()` and `MemLimit(newValue)`.
- Added get and set functions for OpsLimit. `OpsLimit()` and `OpsLimit(newValue)`.
### Changed
- `static readonly` configuration default values are now set to their value manually. Previously they were just "re-exports" of sodium-native's constants.
### Removed
- **Possibly Breaking Change:** Removed `getMemLimit()` and `getOpsLimit()` functions, replaced with getters and setters as detailed above.
## [0.1.3] - 2018-09-06
### Added
- Added internal functions to convert buffers to url-safe base64 and back again.

@@ -15,3 +30,3 @@ - Added functions to generate and verify one time authentication buffers. Generates a mac from a supplied message using a random key.

## 0.1.2 - 2018-09-06
## [0.1.2] - 2018-09-06
### Fixed

@@ -21,3 +36,3 @@

## 0.1.1 - 2018-09-06
## [0.1.1] - 2018-09-06
### Fixed

@@ -32,7 +47,11 @@

- Added get functions for the currently configured memory limit and operations limit.
- Added a custom error class <code>SecurePassOptionsError</code> that is thrown if an error occurs during options validation.
- Added <code>hashPassword()</code> function, the function takes a password in as a buffer and provides the hashed output. The function can work with any of the following return methods; async/await, promise or callback.
- Added <code>VerificationResult</code> enumeration to serve as the response to the hash verification function.
- Added <code>verifyHash()</code> function, the function takes a password and a hash as buffers and provides a <code>VerificationResult</code> as an output. The function can work with any of the following return methods; async/await, promise or callback.
- Added a custom error class `SecurePassOptionsError` that is thrown if an error occurs during options validation.
- Added `hashPassword()` function, the function takes a password in as a buffer and provides the hashed output. The function can work with any of the following return methods; async/await, promise or callback.
- Added `VerificationResult` enumeration to serve as the response to the hash verification function.
- Added `verifyHash()` function, the function takes a password and a hash as buffers and provides a `VerificationResult` as an output. The function can work with any of the following return methods; async/await, promise or callback.
<!-- Links -->
[Unreleased]: https://github.com/DrBarnabus/secure-pass/compare/v0.1.3...HEAD
[0.1.3]: https://github.com/DrBarnabus/secure-pass/compare/v0.1.2...v0.1.3
[0.1.2]: https://github.com/DrBarnabus/secure-pass/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/DrBarnabus/secure-pass/compare/v0.1.0...v0.1.1
{
"name": "argon2-pass",
"version": "0.1.3",
"version": "0.2.0",
"description": "State of the art password hashing and one time password reset token generation module written in TypeScript for nodejs.",

@@ -23,2 +23,4 @@ "main": "./dist/index.js",

"tslint": "^5.11.0",
"typedoc": "^0.12.0",
"typedoc-plugin-external-module-name": "^1.1.3",
"typescript": "^3.0.3"

@@ -25,0 +27,0 @@ },

@@ -1,2 +0,2 @@

<p align="center"><img width="60%" src="https://github.com/DrBarnabus/secure-pass/blob/master/media/logo_transparent_background.png"></p>
<p align="center"><a href="https://drbarnabus.github.io/secure-pass/"><img width="60%" src="https://raw.github.com/DrBarnabus/secure-pass/master/media/logo_transparent_background.png"></a></p>

@@ -10,5 +10,6 @@ [![NPM Version][npm-badge]][npm-url]

[![Known Vulnerabilities][snyk-badge]][snyk-url]
[![Code Quality][codacy-badge]][codacy-url]
# Introduction
SecurePass (argon2-pass) is a module for the creation of hashes from passwords, allowing you to store passwords securely. The module also provides a facility for the generation and verification of one time use password reset tokens for use in your own password reset flows. This module is a wrapper for [libsodium]'s implementation of the [Argon2ID] password hashing algorithm.
SecurePass (argon2-pass) is a module for the creation of hashes from passwords, allowing you to store passwords securely. The module also provides a facility for the generation and verification of one time authentication tokens for use in your own password reset flows. This module is a wrapper for [libsodium]'s implementation of the [Argon2ID] password hashing algorithm and Poly1305.

@@ -18,4 +19,6 @@ # Features

- Uses the state of the art, secure modern password hashing algorithm [Argon2ID].
- Uses <code>Buffer</code>'s for safer memory management.
- Allows for generation of one time use password reset tokens to be used in your own password reset flow.
- Uses Buffer's for safer memory management.
- Uses static functions for basic operations, so you don't have to create a new instance every time.
- asynchronous functions are defined to work with async/await, promises and callbacks. Synchronous versions are also available just in-case you don't want your hashing and verification to be asynchronous.
- Allows for generation of one time use authentication tokens to be used in your own password reset flow.
- Easily configurable work factors, allowing you to increase the security of your hashes over time.

@@ -28,6 +31,11 @@ - Three default difficulty configurations for password hashing, as defined in [libsodium]'s implementation. Allowing you to configure your security level based on some recommended predefined values.

To install the package you need to use a package manager such as npm or yarn.
Install argon2-pass using [`yarn`](https://yarnpkg.com/en/package/argon2-pass):
```bash
yarn add argon2-pass
```
yarn add argon2-pass
Or via [`npm`](https://www.npmjs.com/package/argon2-pass):
```bash
npm install argon2-pass

@@ -38,14 +46,52 @@ ```

**Coming Soon**
Basic Usage Information:
```typescript
import { SecurePass, VerificationResult } from 'argon2-pass';
async function main() {
// Create a new instance of SecurePass. Optional difficulty configurations can be passed in here.
const sp = new SecurePass();
// Passwords and Hashes are stored as buffers internally.
const password = Buffer.from('SamplePassword');
const hash = await sp.hashPassword(password);
// Hash Verification returns an enumerator for easy validation of passwords against hashes.
const result = await sp.verifyHash(password, hash);
if (result == VerificationResult.InvalidOrUnrecognised) {
console.log('Hash not created by SecurePass or invalid');
} else if (result == VerificationResult.Invalid) {
console.log('Password not valid when compared with supplied hash');
} else if (result == VerificationResult.Valid) {
console.log('Password and Hash are a match');
} else if (result == VerificationResult.ValidNeedsRehash) {
console.log('Password and Hash are a match, but the security of the hash could be improved by rehashing.');
}
}
// Call the async function defined above to run the example.
main();
```
For full documentation, please refer to the full [documentation site](https://drbarnabus.github.io/secure-pass/globals.html). The documentation was generated automaticaly with [TypeDoc].
# Testing
This package is configured with [jest] tests, these tests ensure that the module is working correctly and as specified as well as generating code coverage reports.
This package is configured with [jest] tests, these tests ensure that the module is working correctly and as specified as well as generating code coverage reports to ensure every line of code is covered by a unit test.
```
To run the jest tests manualy run the test script defined in package.json:
```bash
yarn test
or
npm test
```
This module also has the following automated testing:
- CI Builds on [Travis].
- Code Coverage Reports on [CodeCov].
- Dependency Update Checks on [david-dm].
- Dependency Vulnerabilities Checks on [snyk].
- Automated Code Review and Quality Report on [codacy].
# Acknowledgements

@@ -56,3 +102,3 @@

# Licence
Licensed under [MIT](./LICENSE).
Licensed under [MIT](https://raw.github.com/DrBarnabus/secure-pass/master/LICENSE).

@@ -65,16 +111,25 @@ Copyright (C) 2018 DrBarnabus

[sodium-native]: https://github.com/sodium-friends/sodium-native
[jest]: https://github.com/facebook/jest
[Travis]: https://travis-ci.org/DrBarnabus/secure-pass
[CodeCov]: https://codecov.io/gh/DrBarnabus/secure-pass
[david-dm]: https://david-dm.org/drbarnabus/secure-pass
[snyk]: https://snyk.io/test/github/DrBarnabus/secure-pass?targetFile=package.json
[codacy]: https://www.codacy.com/app/DrBarnabus/secure-pass?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=DrBarnabus/secure-pass&amp;utm_campaign=Badge_Grade
[TypeDoc]: https://github.com/TypeStrong/typedoc
<!-- Badges -->
[npm-badge]: https://img.shields.io/npm/v/argon2-pass.svg?style=flat-square
[npm-badge]: https://img.shields.io/npm/v/argon2-pass.svg
[npm-url]: https://www.npmjs.com/package/argon2-pass
[npmd-badge]: https://img.shields.io/npm/dw/argon2-pass.svg?style=flat-square
[travis-badge]: https://img.shields.io/travis/DrBarnabus/secure-pass/master.svg?style=flat-square
[npmd-badge]: https://img.shields.io/npm/dw/argon2-pass.svg
[travis-badge]: https://travis-ci.org/DrBarnabus/secure-pass.svg?branch=master
[travis-url]: https://travis-ci.org/DrBarnabus/secure-pass
[dependencies-badge]: https://david-dm.org/drbarnabus/argon2-pass.svg?style=flat-square
[codecov-badge]: https://img.shields.io/codecov/c/github/DrBarnabus/secure-pass/master.svg?style=flat-square
[codecov-badge]: https://codecov.io/gh/DrBarnabus/secure-pass/branch/master/graph/badge.svg
[codecov-url]: https://codecov.io/gh/DrBarnabus/secure-pass
[dependencies-url]: https://david-dm.org/drbarnabus/argon2-pass
[devDependencies-badge]: https://david-dm.org/drbarnabus/argon2-pass/dev-status.svg?style=flat-square
[devDependencies-url]: https://david-dm.org/drbarnabus/argon2-pass?type=dev
[snyk-badge]: https://snyk.io/test/github/DrBarnabus/secure-pass/badge.svg?targetFile=package.json&style=flat-square
[snyk-url]: https://snyk.io/test/github/DrBarnabus/secure-pass?targetFile=package.json
[dependencies-badge]: https://david-dm.org/drbarnabus/secure-pass.svg
[dependencies-url]: https://david-dm.org/drbarnabus/secure-pass
[devDependencies-badge]: https://david-dm.org/drbarnabus/secure-pass/dev-status.svg
[devDependencies-url]: https://david-dm.org/drbarnabus/secure-pass?type=dev
[snyk-badge]: https://snyk.io/test/github/DrBarnabus/secure-pass/badge.svg?targetFile=package.json
[snyk-url]: https://snyk.io/test/github/DrBarnabus/secure-pass?targetFile=package.json
[codacy-badge]: https://api.codacy.com/project/badge/Grade/86e94a6a25c44d7bb7e514e7e2747e24
[codacy-url]: https://www.codacy.com/app/DrBarnabus/secure-pass?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=DrBarnabus/secure-pass&amp;utm_campaign=Badge_Grade

@@ -1,2 +0,2 @@

import { bufferFromSafeBase64, bufferToSafeBase64 } from '../base64';
import { bufferFromSafeBase64, bufferToSafeBase64 } from '..';

@@ -3,0 +3,0 @@ describe('base64', () => {

import sodium from 'sodium-native';
import { GenerateOneTimeAuthResult, SecurePass, VerificationResult } from '../';
import { SecurePass, VerificationResult } from '..';
import { SecurePassError, SecurePassOptionsError } from '../error';

@@ -19,2 +19,10 @@

test('MacBytes Constant should be defined.', () => {
expect(SecurePass.MacBytes).toBeDefined();
});
test('KeyBytes Constant should be defined.', () => {
expect(SecurePass.KeyBytes).toBeDefined();
});
test('MemLimit* Constants should be defined.', () => {

@@ -49,4 +57,4 @@ expect(SecurePass.MemLimitDefault).toBeDefined();

const sp = new SecurePass();
expect(sp.getMemLimit()).toEqual(sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE);
expect(sp.getOpsLimit()).toEqual(sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE);
expect(sp.MemLimit).toEqual(sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE);
expect(sp.OpsLimit).toEqual(sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE);
});

@@ -56,4 +64,4 @@

const sp = new SecurePass({});
expect(sp.getMemLimit()).toEqual(sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE);
expect(sp.getOpsLimit()).toEqual(sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE);
expect(sp.MemLimit).toEqual(sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE);
expect(sp.OpsLimit).toEqual(sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE);
});

@@ -65,4 +73,4 @@

});
expect(sp.getMemLimit()).toEqual(16384);
expect(sp.getOpsLimit()).toEqual(sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE);
expect(sp.MemLimit).toEqual(16384);
expect(sp.OpsLimit).toEqual(sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE);
});

@@ -74,4 +82,4 @@

});
expect(sp.getMemLimit()).toEqual(sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE);
expect(sp.getOpsLimit()).toEqual(12);
expect(sp.MemLimit).toEqual(sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE);
expect(sp.OpsLimit).toEqual(12);
});

@@ -83,3 +91,3 @@

});
expect(sp.getMemLimit()).toEqual(SecurePass.MemLimitMinimum);
expect(sp.MemLimit).toEqual(SecurePass.MemLimitMinimum);
});

@@ -91,3 +99,3 @@

});
expect(sp.getMemLimit()).toEqual(SecurePass.MemLimitMaximum);
expect(sp.MemLimit).toEqual(SecurePass.MemLimitMaximum);
});

@@ -99,3 +107,3 @@

});
expect(sp.getOpsLimit()).toEqual(SecurePass.OpsLimitMinimum);
expect(sp.OpsLimit).toEqual(SecurePass.OpsLimitMinimum);
});

@@ -107,3 +115,3 @@

});
expect(sp.getOpsLimit()).toEqual(SecurePass.OpsLimitMaximum);
expect(sp.OpsLimit).toEqual(SecurePass.OpsLimitMaximum);
});

@@ -132,2 +140,58 @@

});
describe('get and set - MemLimit', () => {
test('MemLimit should return the currently configured Memory Limit.', () => {
const sp = new SecurePass({
memLimit: SecurePass.MemLimitSensitive
});
expect(sp.MemLimit).toEqual(SecurePass.MemLimitSensitive);
});
test('MemLimit should set the configured Memory Limit to the new limit.', () => {
const sp = new SecurePass();
sp.MemLimit = SecurePass.MemLimitModerate;
expect(sp.MemLimit).toEqual(SecurePass.MemLimitModerate);
});
test('MemLimit should throw an error if set with an invalid memory limit.', () => {
const sp = new SecurePass();
try {
sp.MemLimit = 1024;
} catch (e) {
expect(e instanceof SecurePassOptionsError).toBeTruthy();
}
});
});
describe('get and set - OpsLimit', () => {
test('OpsLimit should return the currently configured Memory Limit.', () => {
const sp = new SecurePass({
opsLimit: SecurePass.OpsLimitSensitive
});
expect(sp.OpsLimit).toEqual(SecurePass.OpsLimitSensitive);
});
test('OpsLimit should set the configured Memory Limit to the new limit.', () => {
const sp = new SecurePass();
sp.OpsLimit = SecurePass.OpsLimitModerate;
expect(sp.OpsLimit).toEqual(SecurePass.OpsLimitModerate);
});
test('OpsLimit should throw an error if set with an invalid memory limit.', () => {
const sp = new SecurePass();
try {
sp.OpsLimit = SecurePass.OpsLimitMaximum + 1;
} catch (e) {
expect(e instanceof SecurePassOptionsError).toBeTruthy();
}
});
});
});

@@ -275,2 +339,31 @@

describe('hashPasswordSync', () => {
test('Should return a valid hash if given a valid password.', done => {
const sp = new SecurePass();
const password = Buffer.from('SecurePass');
const hash = sp.hashPasswordSync(password);
expect(hash.length).toEqual(SecurePass.HashBytes);
expect(sp.verifyHashSync(password, hash)).toEqual(VerificationResult.Valid);
done();
});
test('Should throw an error if given a blank password buffer.', done => {
const sp = new SecurePass();
const password = Buffer.from('');
try {
const hash = sp.hashPasswordSync(password);
} catch (e) {
expect(e).toBeDefined();
expect(e instanceof SecurePassError).toBeTruthy();
}
done();
});
});
describe('async/promise verifyHash()', () => {

@@ -310,10 +403,10 @@ test('Should correctly verify a valid hashed password.', async () => {

const rehashValid = await bsp.verifyHash(userPassword, weakHash);
const rehashValid = bsp.verifyHashSync(userPassword, weakHash);
expect(rehashValid).toEqual(VerificationResult.ValidNeedsRehash);
const betterHash = await bsp.hashPassword(userPassword);
const betterValid = await bsp.verifyHash(userPassword, betterHash);
const betterValid = bsp.verifyHashSync(userPassword, betterHash);
expect(betterValid).toEqual(VerificationResult.Valid);
const betterInvalid = await bsp.verifyHash(wrongPassword, betterHash);
const betterInvalid = bsp.verifyHashSync(wrongPassword, betterHash);
expect(betterInvalid).toEqual(VerificationResult.Invalid);

@@ -488,2 +581,85 @@ });

});
describe('verifyHashSync()', () => {
test('Should correctly verify a valid hashed password.', () => {
const sp = new SecurePass();
const password = Buffer.from('SecurePass');
const hash = sp.hashPasswordSync(password);
const result = sp.verifyHashSync(password, hash);
expect(result).toBeDefined();
expect(result).toEqual(VerificationResult.Valid);
});
test('Should correctly rehash passwords.', () => {
const wsp = new SecurePass({
memLimit: SecurePass.MemLimitDefault,
opsLimit: SecurePass.OpsLimitDefault
});
const userPassword = Buffer.from('SecurePass');
const wrongPassword = Buffer.from('SecurePass2');
const weakHash = wsp.hashPasswordSync(userPassword);
const weakValid = wsp.verifyHashSync(userPassword, weakHash);
expect(weakValid).toEqual(VerificationResult.Valid);
const weakInvalid = wsp.verifyHashSync(wrongPassword, weakHash);
expect(weakInvalid).toEqual(VerificationResult.Invalid);
const bsp = new SecurePass({
memLimit: SecurePass.MemLimitDefault + 1024,
opsLimit: SecurePass.OpsLimitDefault + 1
});
const rehashValid = bsp.verifyHashSync(userPassword, weakHash);
expect(rehashValid).toEqual(VerificationResult.ValidNeedsRehash);
const betterHash = bsp.hashPasswordSync(userPassword);
const betterValid = bsp.verifyHashSync(userPassword, betterHash);
expect(betterValid).toEqual(VerificationResult.Valid);
const betterInvalid = bsp.verifyHashSync(wrongPassword, betterHash);
expect(betterInvalid).toEqual(VerificationResult.Invalid);
});
test('Should return an error if given a blank password buffer.', () => {
const sp = new SecurePass();
try {
const password = Buffer.from('');
const hash = Buffer.alloc(SecurePass.HashBytes);
const result = sp.verifyHashSync(password, hash);
} catch (e) {
expect(e).toBeDefined();
expect(e instanceof SecurePassError).toBeTruthy();
}
});
test('Should return an error if given a blank hash buffer.', () => {
const sp = new SecurePass();
try {
const password = Buffer.from('SecurePass');
const hash = Buffer.from('');
const result = sp.verifyHashSync(password, hash);
} catch (e) {
expect(e).toBeDefined();
expect(e instanceof SecurePassError).toBeTruthy();
}
});
test('Should return InvalidOrUnrecognized if given an invalid hash buffer.', () => {
const sp = new SecurePass();
const password = Buffer.from('SecurePass');
const hash = Buffer.alloc(SecurePass.HashBytes, 0);
const result = sp.verifyHashSync(password, hash);
expect(result).toEqual(VerificationResult.InvalidOrUnrecognized);
});
});
});

@@ -0,1 +1,9 @@

/**
* @module SecurePass
*/
/**
* Converts a buffer into url-safe base64.
* @param buf - The Buffer to convert.
*/
export function bufferToSafeBase64(buf: Buffer): string {

@@ -9,2 +17,6 @@ return buf

/**
* Converts a url-safe base64 string into a buffer.
* @param base64 - The base64 string to convert.
*/
export function bufferFromSafeBase64(base64: string): Buffer {

@@ -11,0 +23,0 @@ base64 = base64 + '==='.slice((base64.length + 3) % 4);

@@ -0,1 +1,4 @@

/**
* Standard SecurePass module error, returned if anything goes wrong when using the module.
*/
export class SecurePassError extends Error {

@@ -2,0 +5,0 @@ constructor(m: string) {

@@ -0,1 +1,4 @@

/**
* This error is thrown if the supplied options are invalid during creation of an instance of SecurePass.
*/
export class SecurePassOptionsError extends Error {

@@ -2,0 +5,0 @@ constructor(m: string) {

@@ -0,1 +1,5 @@

/**
* @module SecurePass
*/
import sodium from 'sodium-native';

@@ -6,6 +10,9 @@ import { bufferFromSafeBase64, bufferToSafeBase64 } from './base64';

export { SecurePassError, SecurePassOptionsError } from './error';
export { bufferFromSafeBase64, bufferToSafeBase64 } from './base64';
/** A set of configuration options used to configure a new instance of SecurePass */
export interface SecurePassOptions {
/**
* Configures the memory limit of Argon2ID.
* Configures the memory limit of Argon2ID. This value is in bytes.
* The default value is 64MB.
*/

@@ -16,2 +23,3 @@ memLimit?: number;

* Configures the operation limit of Argon2ID.
* The default value is 2.
*/

@@ -21,20 +29,34 @@ opsLimit?: number;

/** The callback function signature when hashPassword is used with a callback. */
export type HashPasswordCallback = (err: SecurePassError | null, hash?: Buffer) => void;
/** The callback function signature when verifyHash is used with a callback. */
export type VerifyHashCallback = (err: SecurePassError | null, result?: VerificationResult) => void;
export enum VerificationResult {
/** Returned if the hash is in an invalid format or wasn't created by SecurePass. */
InvalidOrUnrecognized,
/** Returned if the hash doesn't match the supplied plaintext password. */
Invalid,
/** Returned if the hash is valid and matches the supplied plaintext password. */
Valid,
/** Returned if the hash is valid, but could be improved with the currently set difficulty options. */
ValidNeedsRehash
}
/** Used to return a One Time Authentication mac and key as well as the message it was derrived from. */
export interface GenerateOneTimeAuthResult {
/** One Time Authentication mac. */
mac: Buffer;
/** One Time Authentication message. */
message: Buffer;
/** One Time Authentication randomly generated key. This value should be kept secret. */
key: Buffer;
}
/** Used to return a One Time Authentication Code and randomly generated key. */
export interface GenerateOneTimeAuthCodeResult {
/** One Time Authentication mac and message stored as a specifically formatted base64 string. */
code: string;
/** One Time Authentication randomly generated key. This value should be kept secret. */
key: Buffer;

@@ -48,3 +70,3 @@ }

*/
public static readonly PasswordBytesMin: number = sodium.crypto_pwhash_PASSWD_MIN;
public static readonly PasswordBytesMin: number = 1;

@@ -55,3 +77,3 @@ /**

*/
public static readonly PasswordBytesMax: number = sodium.crypto_pwhash_PASSWD_MAX;
public static readonly PasswordBytesMax: number = 4294967295;

@@ -62,3 +84,3 @@ /**

*/
public static readonly HashBytes: number = sodium.crypto_pwhash_STRBYTES;
public static readonly HashBytes: number = 128;

@@ -69,38 +91,59 @@ /**

*/
public static readonly SaltBytes: number = sodium.crypto_pwhash_SALTBYTES;
public static readonly SaltBytes: number = 16;
/**
* Length of the Mac buffer returned by generateOneTimeAuth.
* @readonly
*/
public static readonly MacBytes: number = 16;
/**
* Length of the secret Key buffer returned by generateOneTimeAuth and generateOneTimeAuthCode.
* @readonly
*/
public static readonly KeyBytes: number = 32;
/**
* Default Memory Limit. 64MB.
* @readonly
*/
public static readonly MemLimitDefault: number = sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE;
public static readonly MemLimitDefault: number = 67108864;
/**
* Interactive Memory Limit. 64MB. For a use case, please see the SecurePass documentation.
* Interactive Memory Limit. 64MB. This value is the same as MemLimitDefault.
* This memory limit is recommended for interactive "online" applications, when combined with OpsLimitInteractive,
* this option requires 64 MiB of dedicated RAM and provides a baseline configuration for web app security.
* Choosing a higher value such as MemLimitModerate, MemLimitSensitive or a custom value may improve security.
* @readonly
*/
public static readonly MemLimitInteractive: number = sodium.crypto_pwhash_MEMLIMIT_INTERACTIVE;
public static readonly MemLimitInteractive: number = 67108864;
/**
* Moderate Memory Limit. 256MB. For a use case, please see the SecurePass documentation.
* Moderate Memory Limit. 256MB.
* This memory limit, combined with OpsLimitModerate provides a good performance and security baseline for
* applications that require higher security than the default/interactive preset.
* Use of this option requires a minimum of 256 MiB of dedicated RAM.
* @readonly
*/
public static readonly MemLimitModerate: number = sodium.crypto_pwhash_MEMLIMIT_MODERATE;
public static readonly MemLimitModerate: number = 268435456;
/**
* Sensitive Memory Limit. 1GB. For a use case, please see the SecurePass documentation.
* Sensitive Memory Limit. 1GB.
* This memory limit, combined with OpsLimitSensitive, is recommended for highly sensitive data
* and non-interactive operations.
* Use of this option requires a minimum of 1024 MiB of dedicated RAM.
*/
public static readonly MemLimitSensitive: number = sodium.crypto_pwhash_MEMLIMIT_SENSITIVE;
public static readonly MemLimitSensitive: number = 1073741824;
/**
* Minimum Memory Limit. 8KB.
* The Minimum Allowed Memory Limit. 8KB.
* @readonly
*/
public static readonly MemLimitMinimum: number = sodium.crypto_pwhash_MEMLIMIT_MIN;
public static readonly MemLimitMinimum: number = 8192;
/**
* Maximum Memory Limit. 4TB.
* The Maximum Allowed Memory Limit. 4TB.
* @readonly
*/
public static readonly MemLimitMaximum: number = sodium.crypto_pwhash_MEMLIMIT_MAX;
public static readonly MemLimitMaximum: number = 4398046510080;

@@ -111,37 +154,51 @@ /**

*/
public static readonly OpsLimitDefault: number = sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE;
public static readonly OpsLimitDefault: number = 2;
/**
* Interactive Operations Limit. 2 Operations. For a use case, please see the SecurePass documentation.
* Interactive Operations Limit. 2 Operations.This value is the same as OpsLimitDefault.
* This operations limit is recommended for interactive "online" applications, when combined with MemLimitInteractive,
* this option provides a baseline configuration for web app security.
* Choosing a higher value such as MemLimitModerate, MemLimitSensitive or a custom value may improve security.
* @readonly
*/
public static readonly OpsLimitInteractive: number = sodium.crypto_pwhash_OPSLIMIT_INTERACTIVE;
public static readonly OpsLimitInteractive: number = 2;
/**
* Moderate Operations Limit. 3 Operations. For a use case, please see the SecurePass documentation.
* Moderate Operations Limit. 3 Operations.
* This operations limit, combined with MemLimitModerate provides a good performance and security baseline for
* applications that require higher security than the default/interactive preset.
* Using this options takes around 0.7 seconds to derrive a hash on a 2.8Ghz Core i7 CPU.
* @readonly
*/
public static readonly OpsLimitModerate: number = sodium.crypto_pwhash_OPSLIMIT_MODERATE;
public static readonly OpsLimitModerate: number = 3;
/**
* Sensitive Operations Limit. 4 Operations. For a use case, please see the SecurePass documentation.
* Sensitive Operations Limit. 4 Operations.
* This memory limit, combined with OpsLimitSensitive, is recommended for highly sensitive data
* and non-interactive operations.
* Using this option it takes around 3.5 seconds to derrive a hash on a 2.8Ghz Core i7 CPU.
*/
public static readonly OpsLimitSensitive: number = sodium.crypto_pwhash_OPSLIMIT_SENSITIVE;
public static readonly OpsLimitSensitive: number = 4;
/**
* Minimum Operations Limit. 1 Operation.
* The Minimum Allowed Operations Limit. 1 Operation.
* @readonly
*/
public static readonly OpsLimitMinimum: number = sodium.crypto_pwhash_OPSLIMIT_MIN;
public static readonly OpsLimitMinimum: number = 1;
/**
* Maximum Operations Limit. 4294967295 Operations.
* The Maximum Allowed Operations Limit. 4294967295 Operations.
* @readonly
*/
public static readonly OpsLimitMaximum: number = sodium.crypto_pwhash_OPSLIMIT_MAX;
public static readonly OpsLimitMaximum: number = 4294967295;
/**
* Generates a random key, and then uses that key and the supplied message,
* to generate a one time authentication mac.
* @param message - The message to be used as the base of the one time authentication key.
*/
public static generateOneTimeAuth(message: Buffer): GenerateOneTimeAuthResult {
const mac = Buffer.alloc(sodium.crypto_onetimeauth_BYTES);
const mac = Buffer.alloc(SecurePass.MacBytes);
const key = Buffer.alloc(sodium.crypto_onetimeauth_KEYBYTES);
const key = Buffer.alloc(SecurePass.KeyBytes);
sodium.randombytes_buf(key);

@@ -154,2 +211,9 @@

/**
* Verifys the authenticity of the mac using the supplied message and,
* the key returned when generating the mac.
* @param mac - The authentication mac generated by generateOneTimeAuth.
* @param message - The original message used to generate the mac.
* @param key - The authentication key generated by generateOneTimeAuth.
*/
public static verifyOneTimeAuth(mac: Buffer, message: Buffer, key: Buffer): boolean {

@@ -159,2 +223,7 @@ return sodium.crypto_onetimeauth_verify(mac, message, key);

/**
* Generates a random key, and then uses that key and the supplied message,
* to generate a one time authentication code.
* @param message - The message to be used as the base of the one time authentication code.
*/
public static generateOneTimeAuthCode(message: Buffer): GenerateOneTimeAuthCodeResult {

@@ -166,2 +235,7 @@ const ota = SecurePass.generateOneTimeAuth(message);

/**
* Verifys the authenticity of the supplied authentication code using the key returned when generating the code.
* @param code - The one time authentication code generated by generateOneTimeAuthCode.
* @param key - The authentication key generated by generateOneTimeAuthCode.
*/
public static verifyOneTimeAuthCode(code: string, key: Buffer): boolean {

@@ -204,3 +278,2 @@ const message = bufferFromSafeBase64(code.substr(0, code.indexOf('~')));

} else {
// tslint:disable-next-line:max-line-length
throw new SecurePassOptionsError(

@@ -222,3 +295,2 @@ `SecurePass: Invalid Memory Limit Configured. Value must be between ${SecurePass.MemLimitMinimum} and ${

} else {
// tslint:disable-next-line:max-line-length
throw new SecurePassOptionsError(

@@ -236,3 +308,3 @@ `Secure Pass: Invalid Operations Limit Configured. Value must be between ${SecurePass.OpsLimitMinimum} and ${

*/
public getMemLimit(): number {
public get MemLimit(): number {
return this.memLimit;

@@ -242,5 +314,22 @@ }

/**
* Sets the Memory Limit to the new value provided.
* @param newValue - The new Memory Limit.
*/
public set MemLimit(newValue: number) {
// Check configured Memory Limit is within allowed values.
if (newValue >= SecurePass.MemLimitMinimum && newValue <= SecurePass.MemLimitMaximum) {
this.memLimit = newValue;
} else {
throw new SecurePassOptionsError(
`SecurePass: Invalid Memory Limit Configured. Value must be between ${SecurePass.MemLimitMinimum} and ${
SecurePass.MemLimitMaximum
}`
);
}
}
/**
* Returns the currently configured Operations Limit.
*/
public getOpsLimit(): number {
public get OpsLimit(): number {
return this.opsLimit;

@@ -250,4 +339,20 @@ }

/**
* Takes the provided password buffer and returns a Argon2ID hash.
* @param password - The password buffer to be hashed.
* Sets the Operations Limit to the new value provided.
*/
public set OpsLimit(newValue: number) {
// Check configured Operations Limit is within allowed values.
if (newValue >= SecurePass.OpsLimitMinimum && newValue <= SecurePass.OpsLimitMaximum) {
this.opsLimit = newValue;
} else {
throw new SecurePassOptionsError(
`Secure Pass: Invalid Operations Limit Configured. Value must be between ${SecurePass.OpsLimitMinimum} and ${
SecurePass.OpsLimitMaximum
}`
);
}
}
/**
* Takes the provided password and returns the derived Argon2ID hash.
* @param password - The password to be hashed.
* @param callback - Optional callback function.

@@ -266,6 +371,24 @@ */

/**
* Takes the provided password buffer and the hash buffer and returns the result of the verification.
* @param password - The password buffer to be verified.
* @param hash - The has buffer to be verified agains.
* Takes the provided password and returns the derived Argon2ID hash.
* @param password - The password to be hashed.
*/
public hashPasswordSync(password: Buffer): Buffer {
if (!(password.length >= SecurePass.PasswordBytesMin && password.length < SecurePass.PasswordBytesMax)) {
throw new SecurePassError(
`Length of Password Buffer must be between ${SecurePass.PasswordBytesMin} and ${SecurePass.PasswordBytesMax}`
);
}
const hash = Buffer.allocUnsafe(SecurePass.HashBytes);
sodium.crypto_pwhash_str(hash, password, this.opsLimit, this.memLimit);
return hash;
}
/**
* Takes the provided password and the hash buffer
* and returns the result of the verification as an enumeration value.
* @param password - The password to be verified.
* @param hash - The hash to be verified against.
*/
public verifyHash(password: Buffer, hash: Buffer): Promise<VerificationResult>;

@@ -281,5 +404,37 @@ public verifyHash(password: Buffer, hash: Buffer, callback: VerifyHashCallback): void;

/**
* Takes the provided password and the hash buffer
* and returns the result of the verification as an enumeration value.
* @param password - The password to be verified.
* @param hash - The hash to be verified against.
*/
public verifyHashSync(password: Buffer, hash: Buffer): VerificationResult {
if (!(password.length >= SecurePass.PasswordBytesMin && password.length < SecurePass.PasswordBytesMax)) {
throw new SecurePassError(
`Length of Password Buffer must be between ${SecurePass.PasswordBytesMin} and ${SecurePass.PasswordBytesMax}`
);
}
if (hash.length != SecurePass.HashBytes) {
throw new SecurePassError(`Length of Hash Buffer must be between ${SecurePass.HashBytes}`);
}
if (!this.recognizedAlgorithm(hash)) {
return VerificationResult.InvalidOrUnrecognized;
}
if (sodium.crypto_pwhash_str_verify(hash, password) == false) {
return VerificationResult.Invalid;
}
if (sodium.crypto_pwhash_str_needs_rehash(hash, this.opsLimit, this.memLimit)) {
return VerificationResult.ValidNeedsRehash;
}
return VerificationResult.Valid;
}
private async hashPasswordAsync(password: Buffer): Promise<Buffer> {
return new Promise<Buffer>((resolve, reject) => {
if (!(password.length > SecurePass.PasswordBytesMin && password.length < SecurePass.PasswordBytesMax)) {
if (!(password.length >= SecurePass.PasswordBytesMin && password.length < SecurePass.PasswordBytesMax)) {
reject(

@@ -308,3 +463,3 @@ new SecurePassError(

return new Promise<VerificationResult>((resolve, reject) => {
if (!(password.length > SecurePass.PasswordBytesMin && password.length < SecurePass.PasswordBytesMax)) {
if (!(password.length >= SecurePass.PasswordBytesMin && password.length < SecurePass.PasswordBytesMax)) {
reject(

@@ -311,0 +466,0 @@ new SecurePassError(

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc