-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
131 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import type { Algorithm } from './types.js'; | ||
export declare function ab2hex(ab: ArrayBuffer | Uint8Array): string; | ||
export declare function hash(algorithm: Algorithm, str: string): Promise<string>; | ||
export declare function hmac(algorithm: Algorithm, str: string, secret: string): Promise<string>; | ||
export declare function randomBytes(length: number): Uint8Array; | ||
export declare function randomInt(max: number): number; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.randomInt = exports.randomBytes = exports.hmac = exports.hash = exports.ab2hex = void 0; | ||
const encoder = new TextEncoder(); | ||
if (!('crypto' in globalThis)) { | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
globalThis.crypto = require('node:crypto').webcrypto; | ||
} | ||
function ab2hex(ab) { | ||
return [...new Uint8Array(ab)] | ||
.map((x) => x.toString(16).padStart(2, '0')) | ||
.join(''); | ||
} | ||
exports.ab2hex = ab2hex; | ||
async function hash(algorithm, str) { | ||
return ab2hex(await crypto.subtle.digest(algorithm.toUpperCase(), encoder.encode(str))); | ||
} | ||
exports.hash = hash; | ||
async function hmac(algorithm, str, secret) { | ||
const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { | ||
name: 'HMAC', | ||
hash: algorithm, | ||
}, false, ['sign', 'verify']); | ||
return ab2hex(await crypto.subtle.sign('HMAC', key, encoder.encode(str))); | ||
} | ||
exports.hmac = hmac; | ||
function randomBytes(length) { | ||
const ab = new Uint8Array(length); | ||
crypto.getRandomValues(ab); | ||
return ab; | ||
} | ||
exports.randomBytes = randomBytes; | ||
function randomInt(max) { | ||
const ab = new Uint32Array(1); | ||
crypto.getRandomValues(ab); | ||
const randomNumber = ab[0] / (0xffffffff + 1); | ||
return Math.floor(randomNumber * max + 1); | ||
} | ||
exports.randomInt = randomInt; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import type { Challenge, ChallengeOptions, Payload } from './types.js'; | ||
export declare function createChallenge(options: ChallengeOptions): Promise<Challenge>; | ||
export declare function verifySolution(payload: string | Payload, hmacKey: string): Promise<boolean>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.verifySolution = exports.createChallenge = void 0; | ||
const helpers_js_1 = require("./helpers.js"); | ||
const DEFAULT_MAX_NUMBER = 1e6; | ||
const DEFAULT_SALT_LEN = 12; | ||
const DEFAULT_ALG = 'SHA-256'; | ||
async function createChallenge(options) { | ||
const algorithm = options.algorithm || DEFAULT_ALG; | ||
const maxNumber = options.maxNumber || DEFAULT_MAX_NUMBER; | ||
const saltLength = options.saltLength || DEFAULT_SALT_LEN; | ||
const salt = options.salt || (0, helpers_js_1.ab2hex)((0, helpers_js_1.randomBytes)(saltLength)); | ||
const number = options.number === void 0 ? (0, helpers_js_1.randomInt)(maxNumber) : options.number; | ||
const challenge = await (0, helpers_js_1.hash)(algorithm, salt + number); | ||
return { | ||
algorithm, | ||
challenge, | ||
salt, | ||
signature: await (0, helpers_js_1.hmac)(algorithm, challenge, options.hmacKey), | ||
}; | ||
} | ||
exports.createChallenge = createChallenge; | ||
async function verifySolution(payload, hmacKey) { | ||
if (typeof payload === 'string') { | ||
payload = JSON.parse(atob(payload)); | ||
} | ||
const check = await createChallenge({ | ||
algorithm: payload.algorithm, | ||
hmacKey, | ||
number: payload.number, | ||
salt: payload.salt, | ||
}); | ||
return (check.challenge === payload.challenge && | ||
check.signature === payload.signature); | ||
} | ||
exports.verifySolution = verifySolution; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
export type Algorithm = 'SHA-1' | 'SHA-256' | 'SHA-512'; | ||
export interface Challenge { | ||
algorithm: Algorithm; | ||
challenge: string; | ||
salt: string; | ||
signature: string; | ||
} | ||
export interface ChallengeOptions { | ||
algorithm?: Algorithm; | ||
hmacKey: string; | ||
maxNumber?: number; | ||
number?: number; | ||
salt?: string; | ||
saltLength?: number; | ||
} | ||
export interface Payload { | ||
algorithm: Algorithm; | ||
challenge: string; | ||
number: number; | ||
salt: string; | ||
signature: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"type": "commonjs" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "./tsconfig.build.json", | ||
"compilerOptions": { | ||
"outDir": "./cjs/dist", | ||
"module": "commonjs", | ||
"target": "ES2021" | ||
} | ||
} |