Outline
What
- SSH alike public key authentication
- OAuth 2.1 (PKCE) alike signing flow
- IdP that only frontend static site, easy to self-hosting
- general-purpose public service, open source under AGPLv3 (releasing soon)
Why
- identity shouldn't be exclusively tied to email or phone
- per site username / password flow is centralized and out of control
- password managers ease up credential management, but not breaking the loop
- Passkeys so far only leads to vendor look-in, (read: "Passkeys: A Shattered Dream")
How
Code Snippets
auth
import { sign } from './sign.js';
import { stretch } from './stretch.js';
import { SEED, mk_timestamp } from './common.js';
export const auth = pre_auth();
export function pre_auth ({
seed = SEED,
now = mk_timestamp,
} = {}) {
return async function ({ client_id, challenge }: {
client_id: string,
challenge: string,
}, { username, password }: {
username: string,
password: string,
}) {
const entropy = new Uint8Array(await stretch([
password, client_id, username, seed
]));
return sign(challenge, entropy, now());
};
}
stretch
import { pre_PBKDF2 } from './pbkdf2.js';
import { str_to_buf } from './common.js';
const PBKDF2 = pre_PBKDF2({
byte: 32,
hash: 'SHA-512',
iterations: 200_000,
});
export async function stretch ([
head, ...tail
]: [ head: string, ...tail: string[] ]) {
let acc = str_to_buf(head).buffer;
for (const next of tail) {
acc = await PBKDF2({
salt: acc,
passphrase: str_to_buf(next),
});
}
return acc;
}
sign
import { getPublicKeyAsync, signAsync } from '@noble/ed25519';
import { HMAC_SHA256, str_to_buf, type Timestamp } from './common.js';
export const sign = pre_sign();
export function pre_sign ({
HMAC = HMAC_SHA256,
mk_signature = signAsync,
mk_public_key = getPublicKeyAsync,
} = {}) {
return async function (
challenge: string,
entropy: Uint8Array,
timestamp: Timestamp,
) {
const sample = new Uint8Array(await HMAC({
key: str_to_buf(timestamp),
message: str_to_buf(challenge),
}));
const signature = await mk_signature(sample, entropy);
const pub = await mk_public_key(entropy);
return { pub, signature, timestamp };
};
}
Available
main
https://sign-poc.js.org
(GitHub Pages)
mirror
https://sign-poc-mirror.pages.dev
(Cloudflare Pages)