scrypt-kdf
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -7,3 +7,3 @@ { | ||
"repository": { "type": "git", "url": "https://github.com/chrisveness/scrypt-kdf" }, | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"license": "MIT", | ||
@@ -19,6 +19,6 @@ "main": "scrypt.js", | ||
"devDependencies": { | ||
"chai": "^4.1.2", | ||
"eslint": "^5.0.1", | ||
"chai": "^4.2.0", | ||
"eslint": "^5.6.1", | ||
"mocha": "^5.2.0", | ||
"nyc": "^12.0.2" | ||
"nyc": "^13.0.1" | ||
}, | ||
@@ -25,0 +25,0 @@ "eslintConfig": { |
@@ -94,13 +94,13 @@ Scrypt Key Derivation Function | ||
offset | length | value | ||
------:|-------:|:----- | ||
0 | 6 | ‘scrypt’ | ||
6 | 1 | version [0] | ||
7 | 1 | log2(N) | ||
8 | 4 | r (big-endian integer) | ||
12 | 4 | p (big-endian integer) | ||
16 | 32 | salt | ||
48 | 16 | checksum: first 16 bytes of SHA256(bytes 0–47) | ||
64 | 32 | HMAC-SHA256(bytes 0–63), with scrypt(password, salt, 64, { N, r, p }) as key | ||
| offset | length | value | ||
| -----: | -----: | :---- | ||
| 0 | 6 | ‘scrypt’ | ||
| 6 | 1 | version [0] | ||
| 7 | 1 | log2(N) | ||
| 8 | 4 | r (big-endian integer) | ||
| 12 | 4 | p (big-endian integer) | ||
| 16 | 32 | salt | ||
| 48 | 16 | checksum: first 16 bytes of SHA256(bytes 0–47) | ||
| 64 | 32 | HMAC-SHA256(bytes 0–63), with scrypt(password, salt, 64, { N, r, p }) as key | ||
The key will always begin with *c2NyeXB0*, as this is ‘scrypt’ encoded as base-64. |
@@ -23,2 +23,3 @@ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
if (crypto.scrypt == undefined) throw new Error('crypto.scrypt not found: Node.js v10.5.0+ required'); | ||
crypto.scrypt = promisify(crypto.scrypt); | ||
@@ -40,3 +41,3 @@ | ||
* @example | ||
* const key = Scrypt.kdf('my secret password', { logN: 15 }); | ||
* const key = await Scrypt.kdf('my secret password', { logN: 15 }); | ||
*/ | ||
@@ -57,4 +58,5 @@ static async kdf(passphrase, params) { | ||
if (logN < 1 || logN > 30) throw new RangeError(`Parameter logN must be between 1 and 30; received ${params.logN}`); | ||
if (isNaN(r) || r != params.r) throw new RangeError(`Parameter r must be an integer; received ${params.r}`); | ||
if (isNaN(p) || p != params.p) throw new RangeError(`Parameter p must be an integer; received ${params.p}`); | ||
if (isNaN(r) || r != params.r || r <= 0) throw new RangeError(`Parameter r must be a positive integer; received ${params.r}`); | ||
if (isNaN(p) || p != params.p || p <= 0) throw new RangeError(`Parameter p must be a positive integer; received ${params.p}`); | ||
if (p > (2**30-1)/r) throw new RangeError(`Parameters p*r must be <= 2^30-1`); | ||
@@ -126,3 +128,3 @@ // the derived key is 96 bytes: use an ArrayBuffer to view it in different formats | ||
* @example | ||
* const ok = Scrypt.verify(key, 'my secret password'; // => true | ||
* const ok = await Scrypt.verify(key, 'my secret password'); | ||
*/ | ||
@@ -183,3 +185,3 @@ static async verify(key, passphrase) { | ||
} catch (e) { | ||
return false; // ??? | ||
throw new Error(e); // localise error to this function [can't happen?] | ||
} | ||
@@ -247,3 +249,3 @@ } | ||
* @example | ||
* const params = pickParams(0.1); // => e.g. { logN: 15, r: 8, p: 1 } | ||
* const params = Scrypt.pickParams(0.1); // => e.g. { logN: 15, r: 8, p: 1 } | ||
*/ | ||
@@ -250,0 +252,0 @@ static pickParams(maxtime, maxmem=os.totalmem(), maxmemfrac=0.5) { |
@@ -90,20 +90,58 @@ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
describe('kdf errors', function() { | ||
it('throws on numeric passphrase', () => Scrypt.kdf(99).catch(error => expect(error.message).to.equal('Passphrase must be a string'))); | ||
it('throws on no params', () => Scrypt.kdf(password).catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, null).catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, false).catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, 99).catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, 'bad params').catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad logN', () => Scrypt.kdf(password, { logN: 'bad' }).catch(error => expect(error.message).to.equal('Parameter logN must be an integer; received bad'))); | ||
it('throws on zero logN', () => Scrypt.kdf(password, { logN: 0 }).catch(error => expect(error.message).to.equal('Parameter logN must be between 1 and 30; received 0'))); | ||
it('throws on non-integer logN', () => Scrypt.kdf(password, { logN: 12.12 }).catch(error => expect(error.message).to.equal('Parameter logN must be an integer; received 12.12'))); | ||
it('throws on non-integer r', () => Scrypt.kdf(password, { logN: 12, r: 8.8 }).catch(error => expect(error.message).to.equal('Parameter r must be an integer; received 8.8'))); | ||
it('throws on non-integer p', () => Scrypt.kdf(password, { logN: 12, p: 1.1 }).catch(error => expect(error.message).to.equal('Parameter p must be an integer; received 1.1'))); | ||
it('throws on out-of-range r', () => Scrypt.kdf(password, { logN: 12, r: 2**31 }).catch(error => expect(error.message).to.equal('RangeError [ERR_OUT_OF_RANGE]: The value of "r" is out of range. It must be >= 0 && <= 2147483647. Received 2147483648'))); | ||
it('throws on numeric passphrase', () => Scrypt.kdf(99) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Passphrase must be a string'))); | ||
it('throws on no params', () => Scrypt.kdf(password) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, null) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, false) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, 99) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad params', () => Scrypt.kdf(password, 'bad params') | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Params must be an object'))); | ||
it('throws on bad logN', () => Scrypt.kdf(password, { logN: 'bad' }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameter logN must be an integer; received bad'))); | ||
it('throws on zero logN', () => Scrypt.kdf(password, { logN: 0 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameter logN must be between 1 and 30; received 0'))); | ||
it('throws on non-integer logN', () => Scrypt.kdf(password, { logN: 12.12 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameter logN must be an integer; received 12.12'))); | ||
it('throws on non-integer r', () => Scrypt.kdf(password, { logN: 12, r: 8.8 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameter r must be a positive integer; received 8.8'))); | ||
it('throws on non-integer p', () => Scrypt.kdf(password, { logN: 12, p: 1.1 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameter p must be a positive integer; received 1.1'))); | ||
it('throws on 0 r', () => Scrypt.kdf(password, { logN: 12, r: 0 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameter r must be a positive integer; received 0'))); | ||
it('throws on 0 p', () => Scrypt.kdf(password, { logN: 12, p: 0 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameter p must be a positive integer; received 0'))); | ||
it('throws on out-of-range r', () => Scrypt.kdf(password, { logN: 12, r: 2**30 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameters p*r must be <= 2^30-1'))); | ||
it('throws on out-of-range p', () => Scrypt.kdf(password, { logN: 12, p: 2**30 }) | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Parameters p*r must be <= 2^30-1'))); | ||
}); | ||
describe('verify errors', function() { | ||
it('throws on bad key type', async () => Scrypt.verify(await Scrypt.kdf(password, { logN: 12 }), null).catch(error => expect(error.message).to.equal('Passphrase must be a string'))); | ||
it('throws on bad key type', () => Scrypt.verify(null, 'passwd').catch(error => expect(error.message).to.equal('Key must be a string'))); | ||
it('throws on bad key', () => Scrypt.verify('key', 'passwd').catch(error => expect(error.message).to.equal('Invalid key'))); | ||
it('throws on bad key type', async () => Scrypt.verify(await Scrypt.kdf(password, { logN: 12 }), null) | ||
.catch(error => expect(error.message).to.equal('Passphrase must be a string'))); | ||
it('throws on bad key type', () => Scrypt.verify(null, 'passwd') | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Key must be a string'))); | ||
it('throws on bad key', () => Scrypt.verify('key', 'passwd') | ||
.then(() => { throw new Error('Test should fail'); }) | ||
.catch(error => expect(error.message).to.equal('Invalid key'))); | ||
it('throws on checksum failure', async () => { | ||
@@ -110,0 +148,0 @@ const keyBuff = Buffer.from(await Scrypt.kdf(password, { logN: 12 }), 'base64'); |
Sorry, the diff of this file is not supported yet
45812
13
393