39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
hashPassword,
|
|
keyedDigest,
|
|
randomToken,
|
|
safeTokenEquals,
|
|
verifyPassword
|
|
} from '../src/server/security.js'
|
|
|
|
describe('security helpers', () => {
|
|
it('round-trips scrypt password hashes without storing plaintext', async () => {
|
|
const password = 'correct horse battery staple'
|
|
const encoded = await hashPassword(password)
|
|
|
|
expect(encoded).toMatch(/^scrypt\$/u)
|
|
expect(encoded).not.toContain(password)
|
|
await expect(verifyPassword(password, encoded)).resolves.toBe(true)
|
|
await expect(verifyPassword('wrong password', encoded)).resolves.toBe(false)
|
|
await expect(verifyPassword(password, 'invalid')).resolves.toBe(false)
|
|
await expect(
|
|
verifyPassword(password, encoded.replace('$16384$', '$1048576$'))
|
|
).resolves.toBe(false)
|
|
})
|
|
|
|
it('creates random tokens and stable keyed digests', () => {
|
|
const first = randomToken()
|
|
const second = randomToken()
|
|
expect(first).not.toBe(second)
|
|
expect(keyedDigest('secret', 'value')).toBe(
|
|
keyedDigest('secret', 'value')
|
|
)
|
|
expect(keyedDigest('secret', 'value')).not.toBe(
|
|
keyedDigest('other', 'value')
|
|
)
|
|
expect(safeTokenEquals('same', 'same')).toBe(true)
|
|
expect(safeTokenEquals('same', 'different')).toBe(false)
|
|
})
|
|
})
|