diff --git a/package.json b/package.json index fe852a3..ddf9736 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "argon2themax", - "version": "1.0.1", + "version": "1.1.0", "description": "Hash passwords with the most costly Argon2 hash possible", "repository": { "type": "git", diff --git a/src/index.ts b/src/index.ts index ff8ef3f..0b09be5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,6 +49,7 @@ export namespace Measurement { export interface Timing { options: Options; computeTimeMs: number; + hashCost: number; } export interface TimingResult { @@ -119,7 +120,8 @@ export namespace Measurement { lastTiming = { computeTimeMs: msElapsed, - options: _.clone(opts) + options: _.clone(opts), + hashCost: opts.memoryCost * opts.parallelism * opts.timeCost }; context.pendingResult.timings.push(lastTiming); @@ -256,12 +258,13 @@ export namespace Measurement { plain: "this is a super cool password", saltLength: 16, statusCallback: t => { - const ms = `Hashing took ${t.computeTimeMs}ms.`; - const pc = `Parallelism: ${t.options.parallelism}.`; - const mc = `MemoryCost: ${t.options.memoryCost} (${Math.pow(2, t.options.memoryCost) / 1024}MB).`; - const tc = `TimeCost: ${t.options.timeCost}.`; + const ms = `Hashed in ${t.computeTimeMs}ms.`; + const hc = `Cost: ${t.hashCost}.`; + const pc = `P: ${t.options.parallelism}.`; + const mc = `M: ${t.options.memoryCost} (${Math.pow(2, t.options.memoryCost) / 1024}MB).`; + const tc = `T: ${t.options.timeCost}.`; - console.log(`${ms} ${pc} ${mc} ${tc}`); + console.log(`${ms} ${hc} ${pc} ${mc} ${tc}`); return true; } @@ -323,7 +326,7 @@ export namespace Selection { // No options available... if (!timing) { - throw new Error(`No timings found with less than ${maxTimeMs}ms compute time.`); + return this.fastest(); } this.timingsCache[maxTimeMs] = timing; @@ -345,8 +348,8 @@ export namespace Selection { getSortedTimings(timings: Timing[]): Timing[] { return _.orderBy(timings, - ["options.memoryCost", "options.timeCost", "options.parallelism", "computeTimeMs"], - ["asc", "asc", "asc", "asc"]); + ["hashCost", "computeTimeMs"], + ["asc", "asc"]); } } diff --git a/test/index.ts b/test/index.ts index f5ac3ea..d86ada2 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,6 +1,7 @@ import * as mocha from "mocha"; import * as chai from "chai"; import * as argon2 from "../src/index"; +import * as _ from "lodash"; describe("Argon2TheMax", () => { it("can turn it to 11 hundred", async function (): Promise { @@ -27,14 +28,22 @@ describe("Argon2TheMax", () => { chai.assert.isNotNull(selector.select(100)); chai.assert.isNotNull(selector.select(100)); - chai.assert.throw(() => selector.select(0), "No timings found with less than 0ms compute time."); + const timeSortedTimings = _.sortBy(result.timings, "computeTimeMs"); + chai.assert.strictEqual(selector.select(0), _.head(timeSortedTimings), + "The fastest timing should be returned when the requested time is too low."); + + const costSortedTimings = _.orderBy(result.timings, ["hashCost", "computeTimeMs"], ["asc", "asc"]); + chai.assert.strictEqual(selector.select(1000000), _.last(costSortedTimings), + "The highest cost timing should be returned when the requested time is too high."); const fastest = selector.fastest(); chai.assert.isNotNull(fastest); + chai.assert.strictEqual(fastest, _.head(timeSortedTimings), "The fastest() wasn't the fastest"); console.log(`Fastest: ${JSON.stringify(fastest)}`); const slowest = selector.slowest(); chai.assert.isNotNull(slowest); + chai.assert.strictEqual(slowest, _.last(timeSortedTimings), "The slowest() wasn't the slowest"); console.log(`Slowest: ${JSON.stringify(slowest)}`); chai.assert.notDeepEqual(fastest, slowest, "The fastest and slowest options should be different, or something is very wrong.");