diff options
feat: canarytool :3
Diffstat (limited to 'src/routes/canaries/keystore.ts')
-rw-r--r-- | src/routes/canaries/keystore.ts | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/src/routes/canaries/keystore.ts b/src/routes/canaries/keystore.ts index af710ec..1d2aefb 100644 --- a/src/routes/canaries/keystore.ts +++ b/src/routes/canaries/keystore.ts @@ -1,7 +1,10 @@ +import { dev } from "$app/environment"; import { PublicKey, readCleartextMessage, readKey, verify } from "openpgp"; +import { fallbackKeys } from "./fallback-keys"; export const keyStore = new Map<string, PublicKey>(); -export const validateSignature = async (message: string, id: string) => { - await initKeystore; +const will_debug = false; +const debug = dev && will_debug ? console.debug : () => void 0; +const _validateSignature = async (message: string, id: string) => { id = id.toUpperCase(); const key = keyStore.get(id) ?? keyStore.get(id.replace(/ /g, "")); if (!key) throw new Error("Could not find key from keystore"); @@ -14,36 +17,64 @@ export const validateSignature = async (message: string, id: string) => { expectSigned: true, }); return verificationResult.data; +} +export const validateSignature: typeof _validateSignature = async (message, id) => { + await initKeystore; + return _validateSignature(message, id) }; const pushKey = async ({ ids, key, is_url, - expectUserIds, + expect_user_ids, + expect_fingerprint, signed_by, }: { ids?: string[]; - expectUserIds?: string[]; + expect_user_ids?: string[]; + expect_fingerprint?: string; key: string; is_url?: boolean; signed_by?: string; }) => { ids = ids ?? []; if (is_url) { + const url = new URL(key, "https://keys.openpgp.org/vks/v1/by-fingerprint/"); + debug('getting key with url', url) key = await fetch( - new URL(key, "https://keys.openpgp.org/vks/v1/by-fingerprint/"), - {}, - ).then((v) => v.text()); + url, + ).then((v) => v.text()).catch(e => { + if (fallbackKeys.has(key)) { + debug('failed with error', e, 'but found fallback key') + return fallbackKeys.get(key)! + } + else { + debug('failed to fetch key, cannot find fallback') + throw e + } + }); + debug('fetched key', key) + } else { + debug('found key', key) } + if (key === null) + throw new Error('Key is null.') + if (key === '') + throw new Error('Key is empty string.') + if (typeof key !== 'string') + throw new Error(`Expected key with type string, got key of type ${key}`) if (signed_by) { - key = await validateSignature(key, signed_by); + debug('key must be signed by', signed_by) + key = await _validateSignature(key, signed_by); + debug('validated signature') } const parsedKey = await readKey({ armoredKey: key, }).then((v) => v.toPublic()); { + const ids = parsedKey.getUserIDs(); const missingUserIds = - expectUserIds?.filter((v) => !expectUserIds.includes(v)) ?? []; + expect_user_ids?.filter((v) => !ids.includes(v)) ?? []; if (missingUserIds.length) { throw new Error( `Key ${parsedKey.getFingerprint()} is missing User IDs: ${missingUserIds.join( @@ -52,24 +83,34 @@ const pushKey = async ({ ); } } + if (expect_fingerprint && parsedKey.getFingerprint().toUpperCase() !== expect_fingerprint.toUpperCase()) + throw new Error( + `Key ${parsedKey.getFingerprint()} is not ${expect_fingerprint}`, + ); + else if (expect_fingerprint) + debug('fingerprint matches expected fingerprint') + else + debug('no expected fingerprint passed') ids.push( parsedKey.getKeyID().toHex().replace(/ /g, ""), parsedKey.getFingerprint().replace(/ /g, ""), - ...(expectUserIds ?? []), + ...(expect_user_ids ?? []), ); ids = ids.filter((v, i, a) => a.indexOf(v) === i).map((v) => v.toUpperCase()); for (const id of ids) { keyStore.set(id, parsedKey); } + debug('added key', parsedKey, 'with ids', ids, 'to keystore') }; export const initKeystore = (async () => { await pushKey({ - key: "B546778F06BBCC8EC167DB3CD919706487B8B6DE", + key: 'B546778F06BBCC8EC167DB3CD919706487B8B6DE', ids: ["memdmp"], - expectUserIds: [ + expect_user_ids: [ "memdmp <memdmp@estrogen.zone>", "memdmp <memdmp@memeware.net>", ], + expect_fingerprint: 'B546778F06BBCC8EC167DB3CD919706487B8B6DE', is_url: true, }); await pushKey({ @@ -108,12 +149,12 @@ ZQ4KTbprMz8J4AD/bG33f9Kqg3AqehEyU2TldJs9U9Oni5AXGSGfKLJhmQc= `, signed_by: "memdmp <memdmp@memeware.net>", ids: ["canary-sigkey-signing"], + expect_fingerprint: '55D3582CAE78601990A8CA1DBFD0F9E61CB7D84E' }); await pushKey({ - // TODO: adapt to the relevant url on current domain when up - key: "https://files.catbox.moe/yf4x40.sig", + key: "https://git.estrogen.zone/mem-estrogen-zone.git/plain/static/keys/external/napatha.pgp.sig", ids: ["napatha"], - expectUserIds: ["chef naphtha <naphtha@kyun.host>"], + expect_user_ids: ["chef naphtha <naphtha@kyun.host>"], is_url: true, signed_by: "canary-sigkey-signing", }); |