import { PublicKey, readCleartextMessage, readKey, verify } from "openpgp"; export const keyStore = new Map(); export const validateSignature = async (message: string, id: string) => { await initKeystore; id = id.toUpperCase(); const key = keyStore.get(id) ?? keyStore.get(id.replace(/ /g, "")); if (!key) throw new Error("Could not find key from keystore"); const signedMessage = await readCleartextMessage({ cleartextMessage: message, }); const verificationResult = await verify({ message: signedMessage, verificationKeys: key, expectSigned: true, }); return verificationResult.data; }; const pushKey = async ({ ids, key, is_url, expectUserIds, signed_by, }: { ids?: string[]; expectUserIds?: string[]; key: string; is_url?: boolean; signed_by?: string; }) => { ids = ids ?? []; if (is_url) { key = await fetch( new URL(key, "https://keys.openpgp.org/vks/v1/by-fingerprint/"), {}, ).then((v) => v.text()); } if (signed_by) { key = await validateSignature(key, signed_by); } const parsedKey = await readKey({ armoredKey: key, }).then((v) => v.toPublic()); { const missingUserIds = expectUserIds?.filter((v) => !expectUserIds.includes(v)) ?? []; if (missingUserIds.length) { throw new Error( `Key ${parsedKey.getFingerprint()} is missing User IDs: ${missingUserIds.join( ", ", )}`, ); } } ids.push( parsedKey.getKeyID().toHex().replace(/ /g, ""), parsedKey.getFingerprint().replace(/ /g, ""), ...(expectUserIds ?? []), ); ids = ids.filter((v, i, a) => a.indexOf(v) === i).map((v) => v.toUpperCase()); for (const id of ids) { keyStore.set(id, parsedKey); } }; export const initKeystore = (async () => { await pushKey({ key: "B546778F06BBCC8EC167DB3CD919706487B8B6DE", ids: ["memdmp"], expectUserIds: [ "memdmp ", "memdmp ", ], is_url: true, }); await pushKey({ // TODO: when primary memdmp key rotates, or when this key expires, replace this inline string with a new one key: `-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 - -----BEGIN PGP PUBLIC KEY BLOCK----- Comment: User ID: memdmp canary keysig Comment: Valid from: 22 Nov 2024 18:31:11 Comment: Valid until: 22 Nov 2027 12:00:00 Comment: Type: 255-bit EdDSA (secret key available) Comment: Usage: Signing, Encryption, Certifying User IDs Comment: Fingerprint: 55D3582CAE78601990A8CA1DBFD0F9E61CB7D84E mDMEZ0C/3xYJKwYBBAHaRw8BAQdA5w4ET7V3FmasUc3h9sb0O0/y38LXp+IUV8Wf La95jm20ZG1lbWRtcCBjYW5hcnkga2V5c2lnIDxtZW1kbXAta2V5LWZvci1zaWdu aW5nLWNhbmFyeS1yZWxhdGVkLWtleXMtZm9yLWV4dGVybmFsLXNlcnZpY2VzQGZh a2VtYWlsLnV3dT6ImQQTFgoAQRYhBFXTWCyueGAZkKjKHb/Q+eYct9hOBQJnQL/f AhsDBQkFoz7RBQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEL/Q+eYct9hO X68BAPPBy76J7EWb25+fj/QUD0rYyi/E2kLfGbW+PLhrB/AdAQDl5icCilAI/2xv X4jpGCH9KdJoClIV4g2AyKoEITKBDbg4BGdAv98SCisGAQQBl1UBBQEBB0CcYmml AWFCXVjIerJJrs/GA65EZDwoZowiVVTS99FvaQMBCAeIfgQYFgoAJhYhBFXTWCyu eGAZkKjKHb/Q+eYct9hOBQJnQL/fAhsMBQkFoz7RAAoJEL/Q+eYct9hOr2IA/22U 2rOPevvUoiObv/DeeQlP2mvaQcOCFHp1HVF+4oHrAQDWZiihBvdIESbqm5MH0zLe EkEE03+lW4Zbe25P6MHsBg== =5NPo - -----END PGP PUBLIC KEY BLOCK----- -----BEGIN PGP SIGNATURE----- iIoEARYKADIWIQS1RnePBrvMjsFn2zzZGXBkh7i23gUCZ0DABRQcbWVtZG1wQG1l bWV3YXJlLm5ldAAKCRDZGXBkh7i23vV5AP9K2Q6j6cOGovTVqsWlThK7qxA2Faz+ ZQ4KTbprMz8J4AD/bG33f9Kqg3AqehEyU2TldJs9U9Oni5AXGSGfKLJhmQc= =945T -----END PGP SIGNATURE----- `, signed_by: "memdmp ", ids: ["canary-sigkey-signing"], }); await pushKey({ // TODO: adapt to the relevant url on current domain when up key: "https://files.catbox.moe/yf4x40.sig", ids: ["napatha"], expectUserIds: ["chef naphtha "], is_url: true, signed_by: "canary-sigkey-signing", }); })(); export default keyStore;