import { PublicKey, readCleartextMessage, readKey, verify } from 'openpgp'; export const keyStore = new Map(); export 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'); 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); } }; 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;