Skip to content

Commit

Permalink
feat: signature check
Browse files Browse the repository at this point in the history
  • Loading branch information
whilefoo committed Jun 4, 2024
1 parent 1f5fd83 commit 210d518
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .dev.vars.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
SUPABASE_URL=
SUPABASE_KEY=
GITHUB_TOKEN=
UBIQUIBOT_PUBLIC_KEY=
1 change: 1 addition & 0 deletions src/types/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Type as T, StaticDecode } from "@sinclair/typebox";
export const envSchema = T.Object({
SUPABASE_URL: T.String(),
SUPABASE_KEY: T.String(),
UBIQUIBOT_PUBLIC_KEY: T.String(),
});

export type Env = StaticDecode<typeof envSchema>;
33 changes: 30 additions & 3 deletions src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ export default {
});
}
const webhookPayload = await request.json();
const settings = Value.Decode(commandQueryUserScheme, Value.Default(commandQueryUserScheme, JSON.parse(webhookPayload.settings)));
webhookPayload.eventPayload = JSON.parse(webhookPayload.eventPayload);
webhookPayload.settings = settings;
const signature = webhookPayload.signature;
delete webhookPayload.signature;
if (!(await verifySignature(env.UBIQUIBOT_PUBLIC_KEY, webhookPayload, signature))) {
return new Response(JSON.stringify({ error: `Error: Signature verification failed` }), {
status: 400,
headers: { "content-type": "application/json" },
});
}
webhookPayload.settings = Value.Decode(commandQueryUserScheme, Value.Default(commandQueryUserScheme, webhookPayload.settings));
await run(webhookPayload, env);
return new Response(JSON.stringify("OK"), { status: 200, headers: { "content-type": "application/json" } });
} catch (error) {
Expand All @@ -36,3 +42,24 @@ function handleUncaughtError(error: unknown) {
const status = 500;
return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } });
}

async function verifySignature(publicKeyPem: string, payload: unknown, signature: string) {
const pemContents = publicKeyPem.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").trim();
const binaryDer = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0));

const publicKey = await crypto.subtle.importKey(
"spki",
binaryDer.buffer,
{
name: "RSASSA-PKCS1-v1_5",
hash: "SHA-256",
},
true,
["verify"]
);

const signatureArray = Uint8Array.from(atob(signature), (c) => c.charCodeAt(0));
const dataArray = new TextEncoder().encode(JSON.stringify(payload));

return await crypto.subtle.verify("RSASSA-PKCS1-v1_5", publicKey, signatureArray, dataArray);
}

0 comments on commit 210d518

Please sign in to comment.