Compare commits

..

3 commits

2 changed files with 83 additions and 28 deletions

26
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/index.js"
},
{
"type": "node",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"name": "Run tests",
"program": "${workspaceFolder}/node_modules/mocha/bin/mocha.js"
}
]
}

View file

@ -13,7 +13,7 @@ describe('hashing and verification', function () {
salt.length.should.eq(32) salt.length.should.eq(32)
key.length.should.eq(86) key.length.should.eq(86)
Buffer.from(key, 'base64url').length.should.eq(64) Buffer.from(key, 'base64url').length.should.eq(64)
scrypt.verify(derived, pass).should.eventually.be.true await scrypt.verify(derived, pass).should.eventually.be.true
}) })
}) })
describe('hashSync() and sync verification', function () { describe('hashSync() and sync verification', function () {
@ -31,35 +31,37 @@ describe('hashSync() and sync verification', function () {
describe('hash() error cases', function () { describe('hash() error cases', function () {
it('throws an error when it receives an invalid cost value', async function () { it('throws an error when it receives an invalid cost value', async function () {
scrypt await scrypt
.hash('bad password', { cost: 2.3 }) .hash('bad password', { cost: 2.3 })
.should.be.rejectedWith(scrypt.InvalidOptions) .should.be.rejectedWith(scrypt.InvalidOptions)
scrypt await scrypt
.hash('bad password', { cost: 2 /* too small */ }) .hash('bad password', { cost: 2 /* too small */ })
.should.be.rejectedWith(scrypt.InvalidOptions) .should.be.rejectedWith(scrypt.InvalidOptions)
}) })
it('throws an error when it receives an invalid keyLength value', async function () { it('throws an error when it receives an invalid keyLength value', async function () {
scrypt await scrypt
.hash('bad password', { keyLength: 2.3 }) .hash('bad password', { keyLength: 2.3 })
.should.be.rejectedWith(scrypt.InvalidOptions) .should.be.rejectedWith(scrypt.InvalidOptions)
}) })
it('throws an error when it receives an invalid saltLength value', async function () { it('throws an error when it receives an invalid saltLength value', async function () {
scrypt await scrypt
.hash('bad password', { saltLength: 2.3 }) .hash('bad password', { saltLength: 2.3 })
.should.be.rejectedWith(scrypt.InvalidOptions) .should.be.rejectedWith(scrypt.InvalidOptions)
scrypt await scrypt
.hash('bad password', { saltLength: 15 /* too small */ }) .hash('bad password', { saltLength: 15 /* too small */ })
.should.be.rejectedWith(scrypt.InvalidOptions) .should.be.rejectedWith(scrypt.InvalidOptions)
}) })
it('throws an error when the password is not the right thing', function () { it('throws an error when the password is not the right thing', async function () {
scrypt.hash(undefined).should.be.rejected await Promise.all([
scrypt.hash(null).should.be.rejected scrypt.hash(undefined).should.be.rejected,
scrypt.hash(123.4).should.be.rejected scrypt.hash(null).should.be.rejected,
scrypt.hash(NaN).should.be.rejected scrypt.hash(123.4).should.be.rejected,
scrypt.hash(['some', 'arbitrary', 'values']).should.be.rejected scrypt.hash(NaN).should.be.rejected,
scrypt.hash({ some: 'arbitrary values' }).should.be.rejected scrypt.hash(['some', 'arbitrary', 'values']).should.be.rejected,
scrypt.hash(Symbol('something else')).should.be.rejected scrypt.hash({ some: 'arbitrary values' }).should.be.rejected,
scrypt.hash(() => "no, you can't do this either").should.be.rejected scrypt.hash(Symbol('something else')).should.be.rejected,
scrypt.hash(() => "no, you can't do this either").should.be.rejected,
])
}) })
}) })
@ -102,20 +104,22 @@ describe('hashSync() error cases', function () {
}) })
describe('verify() error cases', function () { describe('verify() error cases', function () {
it('throws an error when the password is not the right thing', function () { it('throws an error when the password is not the right thing', async function () {
const validHash = const validHash =
'e.WCu8zB9FHLhXaAf5Svn7NE4ySqB5X45X.ZLpxVwLz1816kmshqXHn12X_4_lZD_0Yl-27KSLLzdhXJ0Fr2huSD7BvoMlBMOMUQBKyKXPzhKI01_Ot-C_w8g' 'e.WCu8zB9FHLhXaAf5Svn7NE4ySqB5X45X.ZLpxVwLz1816kmshqXHn12X_4_lZD_0Yl-27KSLLzdhXJ0Fr2huSD7BvoMlBMOMUQBKyKXPzhKI01_Ot-C_w8g'
scrypt.verify(validHash, undefined).should.be.rejected await Promise.all([
scrypt.verify(validHash, null).should.be.rejected scrypt.verify(validHash, undefined).should.be.rejected,
scrypt.verify(validHash, 123.4).should.be.rejected scrypt.verify(validHash, null).should.be.rejected,
scrypt.verify(validHash, NaN).should.be.rejected scrypt.verify(validHash, 123.4).should.be.rejected,
scrypt.verify(validHash, ['some', 'arbitrary', 'values']).should.be.rejected scrypt.verify(validHash, NaN).should.be.rejected,
scrypt.verify(validHash, { some: 'arbitrary values' }).should.be.rejected scrypt.verify(validHash, ['some', 'arbitrary', 'values']).should.be.rejected,
scrypt.verify(validHash, Symbol('something else')).should.be.rejected scrypt.verify(validHash, { some: 'arbitrary values' }).should.be.rejected,
scrypt.verify(validHash, () => "no, you can't do this either").should.be scrypt.verify(validHash, Symbol('something else')).should.be.rejected,
.rejected scrypt.verify(validHash, () => "no, you can't do this either").should.be
scrypt.verify(validHash, Promise.resolve("no, you can't do this either")) .rejected,
.should.be.rejected scrypt.verify(validHash, Promise.resolve("no, you can't do this either"))
.should.be.rejected,
])
}) })
it('throws an error when the hash is not the expected format', async function () { it('throws an error when the hash is not the expected format', async function () {
const validHash = const validHash =
@ -139,7 +143,7 @@ describe('verify() error cases', function () {
await checkThrows(1234, TypeError) await checkThrows(1234, TypeError)
await checkThrows(null, TypeError) await checkThrows(null, TypeError)
await checkThrows([1, 2, 3], TypeError) await checkThrows([1, 2, 3], TypeError)
scrypt.verify( await scrypt.verify(
{ {
// This is technically valid, why try to prevent it? 🤷 // This is technically valid, why try to prevent it? 🤷
split: () => hashParts, split: () => hashParts,
@ -226,3 +230,28 @@ describe('verifySync() error cases', function () {
checkThrows('') checkThrows('')
}) })
}) })
describe('normalization of unicode characters', function () {
it('works, async', async () => {
const angstromChar = '\xC5ngstrom'
const composed = 'A\u030Angstrom'
const withRingAbove = '\u212Bngstrom'
let hash = await scrypt.hash(angstromChar)
const tests = []
tests.push(scrypt.verify(hash, composed).should.eventually.be.true)
tests.push(scrypt.verify(hash, withRingAbove).should.eventually.be.true)
hash = await scrypt.hash(composed)
tests.push(scrypt.verify(hash, withRingAbove).should.eventually.be.true)
await Promise.all(tests)
})
it('works, sync', () => {
const angstromChar = '\xC5ngstrom'
const composed = 'A\u030Angstrom'
const withRingAbove = '\u212Bngstrom'
let hash = scrypt.hashSync(angstromChar)
scrypt.verifySync(hash, composed).should.be.true
scrypt.verifySync(hash, withRingAbove).should.be.true
hash = scrypt.hashSync(composed)
scrypt.verifySync(hash, withRingAbove).should.be.true
})
})