Socket
Socket
Sign inDemoInstall

argon2

Package Overview
Dependencies
Maintainers
1
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

argon2 - npm Package Compare versions

Comparing version 0.16.2 to 0.17.0

4

index.d.ts

@@ -11,2 +11,3 @@ // Type definitions for argon2 v0.14.0

type?: 0 | 1 | 2;
salt?: Buffer;
raw?: boolean;

@@ -33,3 +34,4 @@ }

export const limits: OptionLimits;
export function hash(plain: Buffer | string, options?: Options): Promise<string>;
export function hash(plain: Buffer | string, options?: Options & {raw: true}): Promise<Buffer>;
export function hash(plain: Buffer | string, options?: Options & {raw?: false}): Promise<string>;
export function verify(hash: string, plain: Buffer | string): Promise<boolean>;

@@ -6,5 +6,5 @@ 'use strict'

const argon2d = 0
const argon2i = 1
const argon2id = 2
const limits = Object.freeze(bindings.limits)
const types = Object.freeze(bindings.types)
const version = bindings.version

@@ -16,14 +16,14 @@ const defaults = Object.freeze({

parallelism: 1,
type: argon2i,
type: types.argon2i,
raw: false
})
const limits = Object.freeze(bindings.limits)
const type2string = []
const rightPad = encoded => encoded + '='.repeat(encoded.length % 4)
const rightTrim = encoded => encoded.replace(/=+$/, '')
module.exports = {
defaults,
limits,
argon2d,
argon2i,
argon2id,

@@ -35,4 +35,3 @@ hash (plain, options) {

for (let key of Object.keys(limits)) {
const max = limits[key].max
const min = limits[key].min
const {max, min} = limits[key]
const value = options[key]

@@ -44,20 +43,97 @@ if (value > max || value < min) {

if ('salt' in options) {
return resolve()
}
crypto.randomBytes(16, (err, salt) => {
if (err) {
reject(err)
return reject(err)
}
bindings.hash(Buffer.from(plain), salt, options, resolve, reject)
options.salt = salt
return resolve()
})
}).then(() => {
return new Promise((resolve, reject) => {
bindings.hash(Buffer.from(plain), options, resolve, reject)
})
}).then(hash => {
return new Promise((resolve, reject) => {
if (options.raw) {
return resolve(hash)
}
const algo = `$${type2string[options.type]}$v=${version}`
const params = [
`m=${1 << options.memoryCost}`,
`t=${options.timeCost}`,
`p=${options.parallelism}`
].join(',')
const base64hash = rightTrim(hash.toString('base64'))
const base64salt = rightTrim(options.salt.toString('base64'))
return resolve([algo, params, base64salt, base64hash].join('$'))
})
})
},
verify (hash, plain) {
if (!/^\$argon2(i|d|id)(\$v=\d+)?\$m=\d+,t=\d+,p=\d+(?:\$[\w+/]+){2}$/.test(hash)) {
return Promise.reject(new Error('Invalid hash, must be in MCF, generated by Argon2.'))
}
verify (hash, plain, options) {
options = Object.assign({}, options)
const parsed = {}
const sections = hash.split('$')
return new Promise((resolve, reject) => {
bindings.verify(Buffer.from(hash), Buffer.from(plain), resolve, reject)
if ('type' in options) {
return resolve()
}
parsed.type = types[sections[1]]
return resolve()
}).then(() => {
return new Promise((resolve, reject) => {
const params = sections[sections.length - 3]
if (!('memoryCost' in options)) {
const memoryCost = /m=(\d+)/.exec(params)
parsed.memoryCost = Math.log2(+memoryCost[1])
}
if (!('timeCost' in options)) {
const timeCost = /t=(\d+)/.exec(params)
parsed.timeCost = +timeCost[1]
}
if (!('parallelism' in options)) {
const parallelism = /p=(\d+)/.exec(params)
parsed.parallelism = +parallelism[1]
}
return resolve()
})
}).then(() => {
return new Promise((resolve, reject) => {
if ('salt' in options) {
return resolve()
}
const salt = sections[sections.length - 2]
parsed.salt = Buffer.from(rightPad(salt), 'base64')
return resolve()
})
}).then(() => {
options = Object.assign({}, defaults, parsed, options)
return new Promise((resolve, reject) => {
return bindings.hash(Buffer.from(plain), options, resolve, reject)
})
}).then(raw => {
const expected = sections[sections.length - 1]
const base64hash = rightTrim(raw.toString('base64'))
return Promise.resolve(base64hash === expected)
})
}
}
for (const k of Object.keys(types)) {
module.exports[k] = types[k]
type2string[types[k]] = k
}
{
"name": "argon2",
"version": "0.16.2",
"version": "0.17.0",
"description": "An Argon2 library for Node",

@@ -9,4 +9,4 @@ "main": "index.js",

"benchmark": "node benchmark.js",
"clean": "node-gyp clean && rm -r .nyc_output",
"test": "tsc -p . && node test-d.js && standard && nyc --reporter=lcov ava"
"clean": "node-gyp clean && rm -rf coverage .nyc_output",
"test": "tsc -p . && node test-d.js && standard index.js && nyc --reporter=lcov jest"
},

@@ -36,6 +36,4 @@ "repository": {

"devDependencies": {
"@types/node": "^8.0.0",
"ava": "^0.22.0",
"babel-plugin-transform-async-to-generator": "^6.16.0",
"mockery": "^2.0.0",
"@types/node": "^9.3.0",
"jest": "^22.0.6",
"nyc": "^11.0.1",

@@ -47,3 +45,3 @@ "sandra": "^0.2.1",

"engines": {
"node": ">=4.0.0"
"node": ">=6.0.0"
},

@@ -50,0 +48,0 @@ "ava": {

# node-argon2
[![Greenkeeper badge](https://badges.greenkeeper.io/ranisalt/node-argon2.svg)](https://greenkeeper.io/)
[![NPM package][npm-image]][npm-url] [![Coverage status][coverage-image]][coverage-url] [![Code Quality][codequality-image]][codequality-url] [![Dependencies][david-dm-image]][david-dm-url] [![Codewake][codewake-image]][codewake-url]
[![NPM package][npm-image]][npm-url] [![Coverage status][coverage-image]][coverage-url] [![Code Quality][codequality-image]][codequality-url] [![Dependencies][david-dm-image]][david-dm-url]
- Linux: [![Linux build status][travis-image]][travis-url]

@@ -231,3 +231,1 @@ - Windows: [![Windows build status][appveyor-image]][appveyor-url]

[david-dm-url]: https://david-dm.org/ranisalt/node-argon2
[codewake-image]: https://www.codewake.com/badges/ask_question_flat_square.svg
[codewake-url]: https://www.codewake.com/p/node-argon2

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

'use strict'
const test = require('ava')
const mockery = require('mockery')
let argon2, defaults, limits
/* global expect, test */
const argon2 = require('argon2')
const {defaults, limits} = argon2
const password = 'password'
const salt = Buffer.alloc(16, 'salt')
// Like argon2's modified base64 implementation, this function truncates any
// Like argon2's modified base64 implementation, expect function truncates any
// trailing '=' characters for a more compact representation.

@@ -23,21 +22,4 @@

mockery.registerMock('crypto', {
randomBytes (size, callback) {
callback(null, Buffer.alloc(size, 'salt'))
}
})
test.before(() => {
mockery.enable({useCleanCache: true, warnOnUnregistered: false})
argon2 = require('./')
defaults = argon2.defaults
limits = argon2.limits
})
test.after(() => {
mockery.disable()
})
test('defaults', t => {
t.deepEqual(defaults, {
test('defaults', () => {
expect(defaults).toEqual({
hashLength: 32,

@@ -52,141 +34,183 @@ timeCost: 3,

test('basic hash', async t => {
t.is(await argon2.hash(password), hashes.argon2i)
test('basic hash', () => {
return argon2.hash(password, {salt}).then(hash => {
expect(hash).toBe(hashes.argon2i)
})
})
test('hash with null in password', async t => {
t.is(await argon2.hash('pass\0word'), hashes.withNull)
test('hash with null in password', () => {
return argon2.hash('pass\0word', {salt}).then(hash => {
expect(hash).toBe(hashes.withNull)
})
})
test('with raw hash', async t => {
t.is((await argon2.hash(password, {raw: true})).equals(hashes.rawArgon2i), true)
test('with raw hash', () => {
return argon2.hash(password, {raw: true, salt}).then(hash => {
expect(hash).toEqual(hashes.rawArgon2i)
})
})
test('with raw hash, null in password', async t => {
t.is((await argon2.hash('pass\0word', {raw: true})).equals(hashes.rawWithNull), true)
test('with raw hash, null in password', () => {
return argon2.hash('pass\0word', {raw: true, salt}).then(hash => {
expect(hash).toEqual(hashes.rawWithNull)
})
})
test('hash with argon2d', async t => {
t.is(await argon2.hash(password, {type: argon2.argon2d}), hashes.argon2d)
test('hash with argon2d', () => {
return argon2.hash(password, {type: argon2.argon2d, salt}).then(hash => {
expect(hash).toBe(hashes.argon2d)
})
})
test('argon2d with raw hash', async t => {
t.is((await argon2.hash(password, {type: argon2.argon2d, raw: true})).equals(hashes.rawArgon2d), true)
test('argon2d with raw hash', () => {
return argon2.hash(password, {type: argon2.argon2d, raw: true, salt}).then(hash => {
expect(hash).toEqual(hashes.rawArgon2d)
})
})
test('hash with argon2id', async t => {
t.is(await argon2.hash(password, {type: argon2.argon2id}), hashes.argon2id)
test('hash with argon2id', () => {
return argon2.hash(password, {type: argon2.argon2id, salt}).then(hash => {
expect(hash).toBe(hashes.argon2id)
})
})
test('argon2id with raw hash', async t => {
t.is((await argon2.hash(password, {type: argon2.argon2id, raw: true})).equals(hashes.rawArgon2id), true)
test('argon2id with raw hash', () => {
return argon2.hash(password, {type: argon2.argon2id, raw: true, salt}).then(hash => {
expect(hash).toEqual(hashes.rawArgon2id)
})
})
test('hash with time cost', async t => {
t.regex(await argon2.hash(password, {timeCost: 4}), /t=4/)
test('hash with time cost', () => {
return argon2.hash(password, {timeCost: 4}).then(hash => {
expect(hash).toMatch(/t=4/)
})
})
test('hash with low time cost', async t => {
await t.throws(argon2.hash(password, {timeCost: limits.timeCost.min - 1}), /invalid timeCost.+between \d+ and \d+/i)
test('hash with low time cost', () => {
return argon2.hash(password, {timeCost: limits.timeCost.min - 1}).catch(err => {
expect(err.message).toMatch(/invalid timeCost.+between \d+ and \d+/i)
})
})
test('hash with high time cost', async t => {
await t.throws(argon2.hash(password, {timeCost: limits.timeCost.max + 1}), /invalid timeCost.+between \d+ and \d+/i)
test('hash with high time cost', () => {
return argon2.hash(password, {timeCost: limits.timeCost.max + 1}).catch(err => {
expect(err.message).toMatch(/invalid timeCost.+between \d+ and \d+/i)
})
})
test('hash with hash length', async t => {
test('hash with hash length', () => {
// 4 bytes ascii == 6 bytes base64
t.regex(await argon2.hash(password, {hashLength: 4}), /\$\w{6}$/)
return argon2.hash(password, {hashLength: 4}).catch(err => {
expect(err.message).toMatch(/\$\w{6}$/)
})
})
test('hash with low hash length', async t => {
await t.throws(argon2.hash(password, {hashLength: limits.hashLength.min - 1}), /invalid hashLength.+between \d+ and \d+/i)
test('hash with low hash length', () => {
return argon2.hash(password, {hashLength: limits.hashLength.min - 1}).catch(err => {
expect(err.message).toMatch(/invalid hashLength.+between \d+ and \d+/i)
})
})
test('hash with high hash length', async t => {
await t.throws(argon2.hash(password, {hashLength: limits.hashLength.max + 1}), /invalid hashLength.+between \d+ and \d+/i)
test('hash with high hash length', () => {
return argon2.hash(password, {hashLength: limits.hashLength.max + 1}).catch(err => {
expect(err.message).toMatch(/invalid hashLength.+between \d+ and \d+/i)
})
})
test('hash with memory cost', async t => {
t.regex(await argon2.hash(password, {memoryCost: 13}), /m=8192/)
test('hash with memory cost', () => {
return argon2.hash(password, {memoryCost: 13}).then(hash => {
expect(hash).toMatch(/m=8192/)
})
})
test('hash with low memory cost', async t => {
await t.throws(argon2.hash(password, {memoryCost: limits.memoryCost.min - 1}), /invalid memoryCost.+between \d+ and \d+/i)
test('hash with low memory cost', () => {
return argon2.hash(password, {memoryCost: limits.memoryCost.min - 1}).catch(err => {
expect(err.message).toMatch(/invalid memoryCost.+between \d+ and \d+/i)
})
})
test('hash with high memory cost', async t => {
await t.throws(argon2.hash(password, {memoryCost: limits.memoryCost.max + 1}), /invalid memoryCost.+between \d+ and \d+/i)
test('hash with high memory cost', () => {
return argon2.hash(password, {memoryCost: limits.memoryCost.max + 1}).catch(err => {
expect(err.message).toMatch(/invalid memoryCost.+between \d+ and \d+/i)
})
})
test('hash with parallelism', async t => {
t.regex(await argon2.hash(password, {parallelism: 2}), /p=2/)
test('hash with parallelism', () => {
return argon2.hash(password, {parallelism: 2}).then(hash => {
expect(hash).toMatch(/p=2/)
})
})
test('hash with low parallelism', async t => {
await t.throws(argon2.hash(password, {parallelism: limits.parallelism.min - 1}), /invalid parallelism.+between \d+ and \d+/i)
test('hash with low parallelism', () => {
return argon2.hash(password, {parallelism: limits.parallelism.min - 1}).catch(err => {
expect(err.message).toMatch(/invalid parallelism.+between \d+ and \d+/i)
})
})
test('hash with high parallelism', async t => {
await t.throws(argon2.hash(password, {parallelism: limits.parallelism.max + 1}), /invalid parallelism.+between \d+ and \d+/i)
test('hash with high parallelism', () => {
return argon2.hash(password, {parallelism: limits.parallelism.max + 1}).catch(err => {
expect(err.message).toMatch(/invalid parallelism.+between \d+ and \d+/i)
})
})
test('hash with all options', async t => {
t.regex(await argon2.hash(password, {timeCost: 4, memoryCost: 13, parallelism: 2}), /m=8192,t=4,p=2/)
test('hash with all options', () => {
return argon2.hash(password, {timeCost: 4, memoryCost: 13, parallelism: 2}).then(hash => {
expect(hash).toMatch(/m=8192,t=4,p=2/)
})
})
test('verify correct password', async t => {
t.true(await argon2.verify(await argon2.hash(password), password))
test('verify correct password', () => {
return argon2.hash(password).then(hash => {
return argon2.verify(hash, password).then(matches => {
expect(matches).toBeTruthy()
})
})
})
test('verify wrong password', async t => {
t.false(await argon2.verify(await argon2.hash(password), 'passworld'))
test('verify wrong password', () => {
return argon2.hash(password).then(hash => {
return argon2.verify(hash, 'passworld').then(matches => {
expect(matches).toBeFalsy()
})
})
})
test('verify invalid hash', async t => {
const hash = await argon2.hash(password)
/* Cut just a piece of the hash making it invalid */
await t.throws(argon2.verify(hash.slice(8), password), /invalid hash.+generated by argon2/i)
test('verify with null in password', () => {
return argon2.hash('pass\0word').then(hash => {
return argon2.verify(hash, 'pass\0word').then(matches => {
expect(matches).toBeTruthy()
})
})
})
test('verify with null in password', async t => {
t.true(await argon2.verify(await argon2.hash('pass\0word'), 'pass\0word'))
test('verify argon2d correct password', () => {
return argon2.hash(password, {type: argon2.argon2d}).then(hash => {
return argon2.verify(hash, password).then(matches => {
expect(matches).toBeTruthy()
})
})
})
test('verify argon2d correct password', async t => {
t.true(await argon2.verify(await argon2.hash(password, {type: argon2.argon2d}), password))
test('verify argon2d wrong password', () => {
return argon2.hash(password, {type: argon2.argon2d}).then(hash => {
return argon2.verify(hash, 'passworld').then(matches => {
expect(matches).toBeFalsy()
})
})
})
test('verify argon2d wrong password', async t => {
t.false(await argon2.verify(await argon2.hash(password, {type: argon2.argon2d}), 'passworld'))
test('verify argon2id correct password', () => {
return argon2.hash(password, {type: argon2.argon2id}).then(hash => {
return argon2.verify(hash, password).then(matches => {
expect(matches).toBeTruthy()
})
})
})
test('verify argon2id correct password', async t => {
t.true(await argon2.verify(await argon2.hash(password, {type: argon2.argon2id}), password))
test('verify argon2id wrong password', () => {
return argon2.hash(password, {type: argon2.argon2id}).then(hash => {
return argon2.verify(hash, 'passworld').then(matches => {
expect(matches).toBeFalsy()
})
})
})
test('verify argon2id wrong password', async t => {
t.false(await argon2.verify(await argon2.hash(password, {type: argon2.argon2id}), 'passworld'))
})
test('js promise + setInterval', async t => {
const timer = setInterval(() => {
/* istanbul ignore next */
t.fail('Interval expired first')
}, 5e3)
await argon2.hash(password)
clearInterval(timer)
t.pass()
})
test('js promise + setTimeout', async t => {
const timer = setTimeout(() => {
/* istanbul ignore next */
t.fail('Timeout expired first')
}, 5e3)
await argon2.hash(password)
clearTimeout(timer)
t.pass()
})

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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