OAuth2 / JWT / OpenID Connect for mocking auth... which isn't that different from doing it for real, actually. https://mock.pocketid.app
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

79 lines
1.5 KiB

'use strict';
/*global crypto*/
var Hashcash = module.exports;
var textEncoder = new TextEncoder();
Hashcash.solve = async function solveHc(hc) {
var solution = 0;
var parts = hc.split(':').slice(0, 6);
if (parts.length < 6) {
throw new Error('invalid Hashcash-Challenge: ' + hc);
}
var bits = parseInt(parts[1], 10) || -1;
if (bits > 10 || bits < 0) {
throw new Error('bad bit values');
}
console.log('bits:', bits);
hc = parts.join(':') + ':';
async function next() {
var answer = hc + int52ToBase64(solution);
var u8 = textEncoder.encode(answer);
// REALLY SLOW due to async tasks and C++ context switch
var hash = await crypto.subtle.digest('SHA-256', u8);
hash = new Uint8Array(hash);
if (checkHc(hash, bits)) {
return answer;
}
solution += 1;
return next();
}
return next();
};
function int52ToBase64(n) {
var hex = n.toString(16);
if (hex.length % 2) {
hex = '0' + hex;
}
var bin = [];
var i = 0;
var d;
var b;
while (i < hex.length) {
d = parseInt(hex.slice(i, i + 2), 16);
b = String.fromCharCode(d);
bin.push(b);
i += 2;
}
return btoa(bin.join('')).replace(/=/g, '');
}
function checkHc(hash, bits) {
var n = Math.floor(bits / 8);
var m = bits % 8;
var i;
if (m > 0) {
n += 1;
}
for (i = 0; i < n && i < hash.length; i += 1) {
if (bits > 8) {
bits -= 8;
if (0 !== hash[i]) {
return false;
}
continue;
}
if (0 !== hash[i] >> (8 - bits)) {
return false;
}
return true;
}
}