Files
classquiz-ai/frontend/src/lib/hashcash.ts
T
2022-07-09 23:02:59 +02:00

60 lines
1.7 KiB
TypeScript

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
import { DateTime } from 'luxon';
const gen_salt = (l: number): string => {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charLength = chars.length;
let result = '';
for (let i = 0; i < l; i++) {
result += chars.charAt(Math.floor(Math.random() * charLength));
}
return result;
};
export const mint = async (
resource: string,
bits = 16,
// now = null,
ext = '',
saltchars = 8,
stamp_seconds = false
): Promise<string> => {
bits = 8;
const ver = '1';
let ts;
if (stamp_seconds) {
ts = DateTime.now().toFormat('yyMMddHHmmss');
} else {
ts = DateTime.now().toFormat('yyMMdd');
}
const hex_digits = Math.ceil(bits / 4);
const zeros = '0'.repeat(hex_digits);
const salt = gen_salt(saltchars);
const challenge = `${ver}:${bits}:${ts}:${resource}:${ext}:${salt}`;
let counter = 0;
let result: string;
const t1 = performance.now();
// eslint-disable-next-line no-constant-condition
while (true) {
const data = new TextEncoder().encode(`${challenge}:${counter.toString(16)}`);
const hashBuffer = await crypto.subtle.digest('SHA-1', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const digest = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
if (digest.slice(0, hex_digits) == zeros) {
result = counter.toString(16);
break;
}
counter += 1;
}
const t2 = performance.now();
// eslint-disable-next-line no-undef
plausible('Hashcash', { props: { ms_taken: t2 - t1 } });
return `${challenge}:${result}`;
};