1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
import { PublicKey, readCleartextMessage, readKey, verify } from "openpgp";
export const keyStore = new Map<string, PublicKey>();
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@estrogen.zone>",
"memdmp <memdmp@memeware.net>",
],
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 <memdmp-key-for-signing-canary-related-keys-for-external-services@fakemail.uwu>
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 <memdmp@memeware.net>",
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 <naphtha@kyun.host>"],
is_url: true,
signed_by: "canary-sigkey-signing",
});
})();
export default keyStore;
|