@@ -0,0 +1,6 @@
|
||||
._*
|
||||
.DS_Store
|
||||
.idea/
|
||||
bun.lockb
|
||||
package-lock.json
|
||||
node_modules/
|
||||
@@ -0,0 +1,22 @@
|
||||
when:
|
||||
- path:
|
||||
include: [
|
||||
'src/**/*.ts',
|
||||
'index.ts'
|
||||
]
|
||||
|
||||
steps:
|
||||
install:
|
||||
image: oven/bun:alpine
|
||||
when:
|
||||
- event: [pull_request, push, manual]
|
||||
commands:
|
||||
- bun install
|
||||
|
||||
test:
|
||||
image: oven/bun:alpine
|
||||
when:
|
||||
- event: [pull_request, push, manual]
|
||||
depends_on: install
|
||||
commands:
|
||||
- bun test
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "crypto-server",
|
||||
"description": "Various crypto utils that only works on the server side",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"files": ["index.ts"],
|
||||
"scripts": {
|
||||
"test": "bun test"
|
||||
},
|
||||
"dependencies": {
|
||||
"jose": "^5.3.0",
|
||||
"result": "git+git@git.pband.ch:typescript/result.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import {Result} from 'result'
|
||||
|
||||
export type JWT = `${string}.${string}.${string}`
|
||||
|
||||
export function create() : Result<JWT> {
|
||||
throw "todo"
|
||||
}
|
||||
export function verify() : boolean {
|
||||
throw "todo"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export function hash(pwd: string) : Promise<string> {
|
||||
return Bun.password.hash(pwd)
|
||||
}
|
||||
|
||||
export async function verify(pwd: string, hash: string) : Promise<boolean> {
|
||||
return Bun.password.verify(pwd, hash).catch(() => false)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import {test, expect} from 'bun:test'
|
||||
|
||||
import {pwd} from '../index'
|
||||
|
||||
test('base case', async () => {
|
||||
const password = "AwesomePassword123!"
|
||||
const hash = await pwd.hash(password)
|
||||
const verification = await pwd.verify(password, hash)
|
||||
expect(verification).toBe(true)
|
||||
})
|
||||
|
||||
test('wrong password', async () => {
|
||||
const password1 = "AwesomePassword123!"
|
||||
const password2 = "AwesomePassword321!"
|
||||
expect(password1).not.toEqual(password2)
|
||||
|
||||
const hash = await pwd.hash(password1)
|
||||
const verification = await pwd.verify(password2, hash)
|
||||
expect(verification).toBe(false)
|
||||
})
|
||||
|
||||
test('salt changes', async () => {
|
||||
const password = "AwesomePassword123!"
|
||||
const hash1 = await pwd.hash(password)
|
||||
const hash2 = await pwd.hash(password)
|
||||
expect(hash1).not.toEqual(hash2)
|
||||
})
|
||||
|
||||
test('tampered hash', async () => {
|
||||
const password = "AwesomePassword123"
|
||||
const hash = await pwd.hash(password)
|
||||
const tamperedHash = hash.replace('a', 'b')
|
||||
const verification = await pwd.verify(password, tamperedHash)
|
||||
expect(verification).toBe(false)
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./src",
|
||||
|
||||
// Enable latest features
|
||||
"lib": ["ESNext"],
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleDetection": "force",
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
},
|
||||
|
||||
"include": [
|
||||
"index.ts",
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user