Skip to content

Commit

Permalink
0.1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
ovx committed Mar 26, 2024
1 parent cb0a90d commit e3ca2a5
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 9 deletions.
6 changes: 6 additions & 0 deletions cjs/dist/helpers.d.ts
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;
39 changes: 39 additions & 0 deletions cjs/dist/helpers.js
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;
3 changes: 3 additions & 0 deletions cjs/dist/index.d.ts
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>;
36 changes: 36 additions & 0 deletions cjs/dist/index.js
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;
22 changes: 22 additions & 0 deletions cjs/dist/types.d.ts
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;
}
2 changes: 2 additions & 0 deletions cjs/dist/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
3 changes: 3 additions & 0 deletions cjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
4 changes: 2 additions & 2 deletions dist/helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const encoder = new TextEncoder();
if (!('crypto' in globalThis)) {
// @ts-ignore
globalThis.crypto = (await import('node:crypto')).webcrypto;
// eslint-disable-next-line @typescript-eslint/no-var-requires
globalThis.crypto = require('node:crypto').webcrypto;
}
export function ab2hex(ab) {
return [...new Uint8Array(ab)]
Expand Down
4 changes: 2 additions & 2 deletions lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import type { Algorithm } from './types.js';
const encoder = new TextEncoder();

if (!('crypto' in globalThis)) {
// @ts-ignore
globalThis.crypto = (await import('node:crypto')).webcrypto;
// eslint-disable-next-line @typescript-eslint/no-var-requires
globalThis.crypto = require('node:crypto').webcrypto;
}

export function ab2hex(ab: ArrayBuffer | Uint8Array) {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "altcha-lib",
"version": "0.1.1",
"version": "0.1.2",
"description": "A library for creating and verifying ALTCHA challenges for Node.js, Bun and Deno.",
"author": "Daniel Regeci",
"license": "MIT",
Expand All @@ -15,20 +15,23 @@
"types": "./dist/index.d.ts",
"type": "module",
"scripts": {
"build": "rimraf dist && tsc -p tsconfig.build.json",
"build": "rimraf dist && rimraf cjs/dist && tsc -b tsconfig.build.json tsconfig.cjs.json",
"denoify": "rimraf deno_dist && denoify && find deno_dist/. -type f -exec sed -i '' -e 's/node:node:/node:/g' {} +",
"eslint": "eslint ./lib/**/*",
"format": "prettier --write './(lib|tests)/**/*'",
"test": "vitest",
"test:deno": "deno test tests/deno.ts"
},
"files": [
"cjs",
"dist"
],
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
"import": "./dist/index.js",
"require": "./cjs/dist/index.js",
"default": "./dist/index.js"
},
"./types": {
"types": "./dist/types.d.ts",
Expand Down
8 changes: 8 additions & 0 deletions tsconfig.cjs.json
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"
}
}

0 comments on commit e3ca2a5

Please sign in to comment.