[TSM.ID].[11031972] PXE : Platform X Ecosystem I [118 Module -LIVE-]
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import crypto from "crypto";
|
||||
import { promises as fs } from "fs";
|
||||
import path from "path";
|
||||
|
||||
function decryptBuffer(vaultPayload: Buffer): Buffer {
|
||||
const rawKey = process.env.QUANTUM_MASTER_KEY || "JUMPA-XCU-ABSOLUTE-SOVEREIGN-KEY";
|
||||
const key = crypto.createHash("sha256").update(rawKey).digest();
|
||||
|
||||
// Ekstrak komponen dari paket vault: [IV (12 bytes)] + [Auth Tag (16 bytes)] + [Encrypted Data]
|
||||
const iv = vaultPayload.subarray(0, 12);
|
||||
const tag = vaultPayload.subarray(12, 28);
|
||||
const encrypted = vaultPayload.subarray(28);
|
||||
|
||||
const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
|
||||
decipher.setAuthTag(tag);
|
||||
|
||||
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
|
||||
}
|
||||
|
||||
export async function GET(
|
||||
req: NextRequest,
|
||||
{ params }: { params: Promise<{ filename: string }> }
|
||||
) {
|
||||
try {
|
||||
const { filename } = await params;
|
||||
|
||||
// Mencegah eksploitasi Path Traversal
|
||||
if (filename.includes("..") || filename.includes("/")) {
|
||||
return NextResponse.json({ error: "Invalid filename" }, { status: 400 });
|
||||
}
|
||||
|
||||
const localDir = process.env.OMNI_LOCAL_DIR || "/var/www/omni-storage";
|
||||
const filePath = path.join(localDir, filename);
|
||||
|
||||
// 1. Baca data terenkripsi (Ciphertext) dari brankas baja lokal
|
||||
const vaultPayload = await fs.readFile(filePath);
|
||||
|
||||
// 2. Dekripsi On-The-Fly (Cleartext) untuk disajikan ke pengguna yang berhak
|
||||
const decryptedBuffer = decryptBuffer(vaultPayload);
|
||||
|
||||
// Deteksi tipe konten dari nama file asli (membuang .vault)
|
||||
const originalExt = filename.replace(".vault", "").split(".").pop()?.toLowerCase();
|
||||
|
||||
let contentType = "application/octet-stream";
|
||||
if (originalExt === "jpg" || originalExt === "jpeg") contentType = "image/jpeg";
|
||||
else if (originalExt === "png") contentType = "image/png";
|
||||
else if (originalExt === "gif") contentType = "image/gif";
|
||||
else if (originalExt === "webp") contentType = "image/webp";
|
||||
else if (originalExt === "pdf") contentType = "application/pdf";
|
||||
else if (originalExt === "mp4") contentType = "video/mp4";
|
||||
|
||||
return new NextResponse(new Uint8Array(decryptedBuffer), {
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": contentType,
|
||||
// Caching agresif karena file objek bersifat immutable
|
||||
"Cache-Control": "public, max-age=31536000, immutable",
|
||||
},
|
||||
});
|
||||
|
||||
} catch (error: unknown) {
|
||||
const msg = error instanceof Error ? error.message : "Unknown error";
|
||||
console.error("[QUANTUM VAULT] Dekripsi gagal atau file hilang:", msg);
|
||||
return NextResponse.json({ error: "Brankas tidak dapat diakses atau kunci enkripsi salah." }, { status: 404 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user