ribaunt 0.1.3 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -286
- package/README.md +258 -0
- package/SECURITY.md +36 -0
- package/context7.json +4 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -17
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/widget-react.d.ts +1 -0
- package/dist/cjs/widget-react.d.ts.map +1 -1
- package/dist/cjs/widget-react.js +9 -6
- package/dist/cjs/widget-react.js.map +1 -1
- package/dist/cjs/widget.d.ts +5 -0
- package/dist/cjs/widget.d.ts.map +1 -1
- package/dist/cjs/widget.js +22 -1
- package/dist/cjs/widget.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -17
- package/dist/index.js.map +1 -1
- package/dist/widget-react.d.ts +1 -0
- package/dist/widget-react.d.ts.map +1 -1
- package/dist/widget-react.js +9 -6
- package/dist/widget-react.js.map +1 -1
- package/dist/widget.d.ts +5 -0
- package/dist/widget.d.ts.map +1 -1
- package/dist/widget.js +22 -1
- package/dist/widget.js.map +1 -1
- package/package.json +7 -8
- package/dist/cjs/index.cjs +0 -200
- package/dist/cjs/index.d.cts +0 -31
- package/scripts/prepare-cjs.mjs +0 -11
package/dist/cjs/index.cjs
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.createChallenge = createChallenge;
|
|
7
|
-
exports.solveChallenge = solveChallenge;
|
|
8
|
-
exports.verifySolution = verifySolution;
|
|
9
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
10
|
-
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
11
|
-
function generateChallenge(length = 8) {
|
|
12
|
-
const buffer = crypto_1.default.randomBytes(length);
|
|
13
|
-
return buffer.toString('base64').slice(0, length);
|
|
14
|
-
}
|
|
15
|
-
function createChallengePayload(difficulty, ttlSeconds) {
|
|
16
|
-
return {
|
|
17
|
-
challenge: generateChallenge(),
|
|
18
|
-
difficulty,
|
|
19
|
-
expires: Math.floor(Date.now() / 1000) + ttlSeconds,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
function getSecret() {
|
|
23
|
-
const secret = process.env.RIBAUNT_SECRET;
|
|
24
|
-
if (!secret) {
|
|
25
|
-
throw new Error('RIBAUNT_SECRET environment variable is not set!');
|
|
26
|
-
}
|
|
27
|
-
return secret;
|
|
28
|
-
}
|
|
29
|
-
function signChallenge(payload) {
|
|
30
|
-
return jsonwebtoken_1.default.sign(payload, getSecret());
|
|
31
|
-
}
|
|
32
|
-
function assertValidAmount(amount) {
|
|
33
|
-
if (!Number.isFinite(amount)) {
|
|
34
|
-
throw new Error('Challenge amount must be a finite number');
|
|
35
|
-
}
|
|
36
|
-
const normalized = Math.floor(amount);
|
|
37
|
-
if (normalized < 1) {
|
|
38
|
-
throw new Error('Challenge amount must be at least 1');
|
|
39
|
-
}
|
|
40
|
-
return normalized;
|
|
41
|
-
}
|
|
42
|
-
function assertValidDifficulty(difficulty) {
|
|
43
|
-
if (!Number.isFinite(difficulty)) {
|
|
44
|
-
throw new Error('Challenge difficulty must be a finite number');
|
|
45
|
-
}
|
|
46
|
-
const normalized = Math.floor(difficulty);
|
|
47
|
-
if (normalized < 1) {
|
|
48
|
-
throw new Error('Challenge difficulty must be at least 1');
|
|
49
|
-
}
|
|
50
|
-
return normalized;
|
|
51
|
-
}
|
|
52
|
-
function assertValidTtl(ttlSeconds) {
|
|
53
|
-
if (!Number.isFinite(ttlSeconds)) {
|
|
54
|
-
throw new Error('Challenge TTL must be a finite number');
|
|
55
|
-
}
|
|
56
|
-
const normalized = Math.floor(ttlSeconds);
|
|
57
|
-
if (normalized < 1) {
|
|
58
|
-
throw new Error('Challenge TTL must be at least 1 second');
|
|
59
|
-
}
|
|
60
|
-
return normalized;
|
|
61
|
-
}
|
|
62
|
-
function createSingleChallenge(difficulty, ttlSeconds) {
|
|
63
|
-
const payload = createChallengePayload(difficulty, ttlSeconds);
|
|
64
|
-
return signChallenge(payload);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Creates one or more PoW challenges and returns them as signed JWT tokens.
|
|
68
|
-
*
|
|
69
|
-
* @param difficulty - Number of leading zeros required in the hash (default 6)
|
|
70
|
-
* @param amount - Number of challenges to create (default 4)
|
|
71
|
-
* @param ttlSeconds - Time to live for each challenge in seconds (default 30)
|
|
72
|
-
* @returns An array of JWT challenge tokens
|
|
73
|
-
*/
|
|
74
|
-
function createChallenge(difficulty = 5, amount = 4, ttlSeconds = 30) {
|
|
75
|
-
const normalizedDifficulty = assertValidDifficulty(difficulty);
|
|
76
|
-
const normalizedAmount = assertValidAmount(amount);
|
|
77
|
-
const normalizedTtl = assertValidTtl(ttlSeconds);
|
|
78
|
-
const challenges = Array.from({ length: normalizedAmount }, () => createSingleChallenge(normalizedDifficulty, normalizedTtl));
|
|
79
|
-
return challenges;
|
|
80
|
-
}
|
|
81
|
-
function solveSingleChallenge(token) {
|
|
82
|
-
try {
|
|
83
|
-
const payload = jsonwebtoken_1.default.decode(token);
|
|
84
|
-
if (!payload)
|
|
85
|
-
return undefined;
|
|
86
|
-
const { challenge, difficulty } = payload;
|
|
87
|
-
const prefix = '0'.repeat(difficulty);
|
|
88
|
-
let nonce = 0;
|
|
89
|
-
while (true) {
|
|
90
|
-
const hash = crypto_1.default
|
|
91
|
-
.createHash('sha256')
|
|
92
|
-
.update(`${challenge}${nonce}`)
|
|
93
|
-
.digest('hex');
|
|
94
|
-
if (hash.startsWith(prefix)) {
|
|
95
|
-
return { nonce: String(nonce), hash };
|
|
96
|
-
}
|
|
97
|
-
nonce++;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
return undefined;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function verifySingleSolution(token, nonce) {
|
|
105
|
-
if (nonce === undefined || nonce === null) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
try {
|
|
109
|
-
const payload = jsonwebtoken_1.default.verify(token, getSecret());
|
|
110
|
-
const now = Math.floor(Date.now() / 1000);
|
|
111
|
-
if (payload.expires < now)
|
|
112
|
-
return false;
|
|
113
|
-
const nonceValue = typeof nonce === 'number' ? String(nonce) : nonce;
|
|
114
|
-
const hash = crypto_1.default
|
|
115
|
-
.createHash('sha256')
|
|
116
|
-
.update(`${payload.challenge}${nonceValue}`)
|
|
117
|
-
.digest('hex');
|
|
118
|
-
const prefix = '0'.repeat(payload.difficulty);
|
|
119
|
-
return hash.startsWith(prefix);
|
|
120
|
-
}
|
|
121
|
-
catch (err) {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
function solveChallenge(token) {
|
|
126
|
-
if (Array.isArray(token)) {
|
|
127
|
-
const solutions = [];
|
|
128
|
-
for (const singleToken of token) {
|
|
129
|
-
const solution = solveSingleChallenge(singleToken);
|
|
130
|
-
if (!solution) {
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
solutions.push(solution);
|
|
134
|
-
}
|
|
135
|
-
return solutions;
|
|
136
|
-
}
|
|
137
|
-
const solution = solveSingleChallenge(token);
|
|
138
|
-
return solution;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Verifies a PoW solution returned by the client.
|
|
142
|
-
*
|
|
143
|
-
* @param token - The original JWT issued as the challenge (single token or array of tokens)
|
|
144
|
-
* @param nonce - The nonce/answer submitted by the client (single nonce, array of nonces, or array of solution objects)
|
|
145
|
-
* @returns true only if every provided solution is valid; otherwise false
|
|
146
|
-
*/
|
|
147
|
-
function verifySolution(token, nonce) {
|
|
148
|
-
if (Array.isArray(token)) {
|
|
149
|
-
let nonces;
|
|
150
|
-
if (Array.isArray(nonce)) {
|
|
151
|
-
if (nonce.length !== token.length) {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
if (nonce.length > 0 && typeof nonce[0] === 'object' && 'nonce' in nonce[0]) {
|
|
155
|
-
nonces = nonce.map(s => s.nonce);
|
|
156
|
-
}
|
|
157
|
-
else {
|
|
158
|
-
nonces = nonce;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
for (let index = 0; index < token.length; index++) {
|
|
165
|
-
const challengeToken = token[index];
|
|
166
|
-
const nonceEntry = nonces[index];
|
|
167
|
-
if (challengeToken === undefined || nonceEntry === undefined) {
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
if (!verifySingleSolution(challengeToken, nonceEntry)) {
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return true;
|
|
175
|
-
}
|
|
176
|
-
let effectiveNonce;
|
|
177
|
-
if (Array.isArray(nonce)) {
|
|
178
|
-
if (nonce.length === 0) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
if (typeof nonce[0] === 'object' && 'nonce' in nonce[0]) {
|
|
182
|
-
effectiveNonce = nonce[0].nonce;
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
effectiveNonce = nonce[0];
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
else if (typeof nonce === 'object' && 'nonce' in nonce) {
|
|
189
|
-
effectiveNonce = nonce.nonce;
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
effectiveNonce = nonce;
|
|
193
|
-
}
|
|
194
|
-
if (effectiveNonce === undefined) {
|
|
195
|
-
return false;
|
|
196
|
-
}
|
|
197
|
-
const result = verifySingleSolution(token, effectiveNonce);
|
|
198
|
-
return result;
|
|
199
|
-
}
|
|
200
|
-
//# sourceMappingURL=index.js.map
|
package/dist/cjs/index.d.cts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export type ChallengeToken = string;
|
|
2
|
-
export interface ChallengeSolution {
|
|
3
|
-
nonce: string;
|
|
4
|
-
hash: string;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Creates one or more PoW challenges and returns them as signed JWT tokens.
|
|
8
|
-
*
|
|
9
|
-
* @param difficulty - Number of leading zeros required in the hash (default 6)
|
|
10
|
-
* @param amount - Number of challenges to create (default 4)
|
|
11
|
-
* @param ttlSeconds - Time to live for each challenge in seconds (default 30)
|
|
12
|
-
* @returns An array of JWT challenge tokens
|
|
13
|
-
*/
|
|
14
|
-
export declare function createChallenge(difficulty?: number, amount?: number, ttlSeconds?: number): ChallengeToken[];
|
|
15
|
-
/**
|
|
16
|
-
* Solves one or more PoW challenges encoded in JWT tokens.
|
|
17
|
-
*
|
|
18
|
-
* @param token - The JWT challenge token or an array of tokens
|
|
19
|
-
* @returns The nonce/hash pair for single input or an array of them for multiple tokens
|
|
20
|
-
*/
|
|
21
|
-
export declare function solveChallenge(token: ChallengeToken): ChallengeSolution | undefined;
|
|
22
|
-
export declare function solveChallenge(token: ChallengeToken[]): ChallengeSolution[] | undefined;
|
|
23
|
-
/**
|
|
24
|
-
* Verifies a PoW solution returned by the client.
|
|
25
|
-
*
|
|
26
|
-
* @param token - The original JWT issued as the challenge (single token or array of tokens)
|
|
27
|
-
* @param nonce - The nonce/answer submitted by the client (single nonce, array of nonces, or array of solution objects)
|
|
28
|
-
* @returns true only if every provided solution is valid; otherwise false
|
|
29
|
-
*/
|
|
30
|
-
export declare function verifySolution(token: ChallengeToken | ChallengeToken[], nonce: number | string | Array<number | string> | ChallengeSolution | ChallengeSolution[]): boolean;
|
|
31
|
-
//# sourceMappingURL=index.d.ts.map
|
package/scripts/prepare-cjs.mjs
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
|
|
4
|
-
const cjsDir = resolve(process.cwd(), 'dist/cjs');
|
|
5
|
-
|
|
6
|
-
await mkdir(cjsDir, { recursive: true });
|
|
7
|
-
await writeFile(
|
|
8
|
-
resolve(cjsDir, 'package.json'),
|
|
9
|
-
`${JSON.stringify({ type: 'commonjs' }, null, 2)}\n`,
|
|
10
|
-
'utf8'
|
|
11
|
-
);
|