diff --git a/functions/api/uploads/[[id]].ts b/functions/api/uploads/[[id]].ts
index 4e36054..c7f00cc 100644
--- a/functions/api/uploads/[[id]].ts
+++ b/functions/api/uploads/[[id]].ts
@@ -1,27 +1,22 @@
+import { AwsClient } from "aws4fetch";
+
 export async function onRequestGet(context: RequestContext) {
   const attachment = (context.params.id as string[]).join("/");
-  const unsignedURL = `https://mediaproxy.carcrushers.cc/${attachment}?Expires=${(
-    Math.round(Date.now() / 1000) + 1800
-  ).toString()}&KeyName=portal-media-linkgen`;
-  const signingKey = await crypto.subtle.importKey(
-    "raw",
-    Uint8Array.from(atob(context.env.URL_SIGNING_KEY), (c) => c.charCodeAt(0)),
-    { hash: "SHA-1", name: "HMAC" },
-    false,
-    ["sign"],
-  );
-  const signature = await crypto.subtle.sign(
-    "HMAC",
-    signingKey,
-    new TextEncoder().encode(unsignedURL),
-  );
+  const aws = new AwsClient({
+    accessKeyId: context.env.R2_ACCESS_KEY,
+    secretAccessKey: context.env.R2_SECRET_KEY,
+  });
 
   return Response.redirect(
-    `${unsignedURL}&Signature=${btoa(
-      String.fromCharCode(...new Uint8Array(signature)),
-    )
-      .replaceAll("+", "-")
-      .replaceAll("/", "_")
-      .replaceAll("=", "")}`,
+    (
+      await aws.sign(
+        `https://car-crushers.${context.env.R2_ZONE}.r2.cloudflarestorage.com/${attachment}?X-Amz-Expires=1800`,
+        {
+          aws: {
+            signQuery: true,
+          },
+        },
+      )
+    ).url,
   );
 }