🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

argon2

Package Overview
Dependencies
Maintainers
1
Versions
79
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

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