Edit: dec64
Nama Worker
Kode Sumber
--1f04fff558f595c26b2b166dbe8ca9919f2463ff35dc17e8d25fe0224976 Content-Disposition: form-data; name="worker.js" /** * Cloudflare Worker: Dekriptor Konten Universal * * FUNGSI: * - Menyediakan antarmuka web untuk mendekripsi konten dari URL. * - Mengunduh konten, lalu mendekripsi menggunakan kunci AES-256-ECB. * - Menampilkan konten asli (Base64) dan hasil dekripsi. * - Ditulis dalam format ES Module modern untuk Cloudflare Workers. * - Semua UI (HTML, CSS, JS) dan logika server ada dalam satu file. */ export default { /** * Titik masuk utama untuk menangani semua permintaan. * @param {Request} request Objek permintaan yang masuk. * @returns {Promise<Response>} Respons yang akan dikirim kembali. */ async fetch(request) { const url = new URL(request.url); // Jika permintaan adalah GET ke halaman utama, tampilkan UI. if (request.method === 'GET' && url.pathname === '/') { return new Response(getHtmlUI(), { headers: { 'Content-Type': 'text/html;charset=UTF-8' }, }); } // Jika permintaan adalah POST ke /decrypt, proses dekripsi. if (request.method === 'POST' && url.pathname === '/decrypt') { return handleDecryptRequest(request); } // Untuk path lain, kembalikan 404 Not Found. return new Response('Halaman tidak ditemukan', { status: 404 }); } }; /** * Menangani logika inti untuk proses dekripsi. * @param {Request} request Permintaan POST yang berisi URL dan Kunci. * @returns {Promise<Response>} Respons JSON berisi hasil atau error. */ async function handleDecryptRequest(request) { try { const { targetUrl, keyB64 } = await request.json(); if (!targetUrl || !keyB64) { throw new Error("URL dan Kunci tidak boleh kosong."); } // 1. Mengunduh konten dari URL target const response = await fetch(targetUrl, { headers: { 'User-Agent': 'Cloudflare-Worker-Decoder/1.0' }}); if (!response.ok) { throw new Error(`Gagal mengunduh konten. Status server: ${response.status}`); } const originalContentB64 = await response.text(); if (!originalContentB64) { throw new Error("Konten yang diunduh dari URL kosong."); } // 2. Melakukan dekripsi const decryptedContent = await decryptAesEcb(originalContentB64, keyB64); // 3. Mengirim kembali hasil return new Response(JSON.stringify({ success: true, originalContent: originalContentB64, decryptedContent: decryptedContent }), { headers: { 'Content-Type': 'application/json' }, }); } catch (error) { // Menangani jika terjadi error selama proses return new Response(JSON.stringify({ success: false, error: error.message }), { status: 400, headers: { 'Content-Type': 'application/json' }, }); } } /** * Fungsi inti untuk mendekripsi teks AES-256-ECB menggunakan Web Crypto API. * @param {string} encryptedBase64 Teks terenkripsi dalam format Base64. * @param {string} keyBase64 Kunci dalam format Base64. * @returns {Promise<string>} Teks hasil dekripsi. */ async function decryptAesEcb(encryptedBase64, keyBase64) { try { const keyBytes = base64ToArrayBuffer(keyBase64); const encryptedBytes = base64ToArrayBuffer(encryptedBase64); const cryptoKey = await crypto.subtle.importKey( "raw", keyBytes, { name: "AES-ECB" }, false, ["decrypt"] ); const decryptedArrayBuffer = await crypto.subtle.decrypt( { name: "AES-ECB" }, cryptoKey, encryptedBytes ); return new TextDecoder().decode(decryptedArrayBuffer); } catch (e) { console.error("Decryption Error:", e); throw new Error("Proses dekripsi gagal. Pastikan kunci dan konten valid. Error ini sering disebabkan oleh kunci yang salah atau padding yang tidak cocok."); } } /** * Fungsi bantuan untuk mengubah string Base64 menjadi ArrayBuffer (data biner). * @param {string} base64 String Base64. * @returns {Uint8Array} Data biner. */ function base64ToArrayBuffer(base64) { const binaryString = atob(base64.replace(/(\r\n|\n|\r)/gm, "")); const len = binaryString.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binaryString.charCodeAt(i); } return bytes; } /** * Menghasilkan seluruh kode HTML, CSS, dan JavaScript untuk antarmuka pengguna. * @returns {string} String HTML lengkap. */ function getHtmlUI() { return ` <!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Dekriptor Konten Universal</title> <script src="https://cdn.tailwindcss.com"></script> <style> body { font-family: 'Inter', sans-serif; } @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap'); textarea { white-space: pre; word-wrap: normal; overflow-x: scroll; } </style> </head> <body class="bg-gray-900 text-white flex items-center justify-center min-h-screen p-4"> <div class="w-full max-w-4xl bg-gray-800 border border-gray-700 rounded-xl shadow-lg p-6 md:p-8 space-y-6"> <div class="text-center"> <h1 class="text-2xl md:text-3xl font-bold text-white">Dekriptor Konten Universal</h1> <p class="text-gray-400 mt-1">Unduh dan dekripsi konten AES-ECB dari URL.</p> </div> <div class="bg-yellow-900 bg-opacity-50 border border-yellow-700 text-yellow-300 px-4 py-3 rounded-md text-sm" role="alert"> <p><strong class="font-bold">Info Keamanan:</strong> Mode enkripsi AES-ECB tidak aman untuk data sensitif karena tidak dapat menyembunyikan pola data. Gunakan alat ini dengan bijak.</p> </div> <form id="decrypt-form" class="space-y-4"> <div> <label for="target-url" class="block text-sm font-medium text-gray-300 mb-1">URL Konten Terenkripsi</label> <input type="url" id="target-url" value="https://raw.githubusercontent.com/RevHunterVPN/RevHunterUPDATES/main/RevHunter/40" class="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition" required> </div> <div> <label for="key-b64" class="block text-sm font-medium text-gray-300 mb-1">Kunci Dekripsi (Base64)</label> <input type="text" id="key-b64" value="I1IM3kpj50r6PYfUfDEOlXWQgLIuZLzoUD1632JvY5k=" class="w-full p-3 bg-gray-700 border border-gray-600 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition" required> </div> <button type="submit" id="submit-button" class="w-full bg-indigo-600 text-white font-bold py-3 px-4 rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition flex items-center justify-center disabled:opacity-50"> <svg id="spinner" class="animate-spin -ml-1 mr-3 h-5 w-5 text-white hidden" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> <span id="button-text">Dekripsi</span> </button> </form> <div id="result-section" class="hidden mt-6 space-y-4"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"> <div> <h2 class="text-lg font-semibold text-gray-200 mb-2">Konten Asli (Terenkripsi)</h2> <textarea id="original-content" rows="10" readonly class="w-full p-3 bg-gray-900 border border-gray-700 rounded-lg text-gray-400 text-xs font-mono"></textarea> </div> <div> <h2 class="text-lg font-semibold text-gray-200 mb-2">Konten Hasil Dekripsi</h2> <textarea id="decrypted-content" rows="10" readonly class="w-full p-3 bg-gray-900 border border-gray-700 rounded-lg text-gray-300 text-xs font-mono"></textarea> </div> </div> </div> <div id="error-box" class="hidden bg-red-900 bg-opacity-50 border border-red-700 text-red-300 px-4 py-3 rounded-md"></div> </div> <script> const form = document.getElementById('decrypt-form'); const submitButton = document.getElementById('submit-button'); const spinner = document.getElementById('spinner'); const buttonText = document.getElementById('button-text'); const resultSection = document.getElementById('result-section'); const errorBox = document.getElementById('error-box'); const originalContentEl = document.getElementById('original-content'); const decryptedContentEl = document.getElementById('decrypted-content'); form.addEventListener('submit', async (e) => { e.preventDefault(); // UI state: Loading submitButton.disabled = true; spinner.classList.remove('hidden'); buttonText.textContent = 'Memproses...'; resultSection.classList.add('hidden'); errorBox.classList.add('hidden'); const payload = { targetUrl: document.getElementById('target-url').value, keyB64: document.getElementById('key-b64').value, }; try { const response = await fetch('/decrypt', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const data = await response.json(); if (!response.ok || !data.success) { throw new Error(data.error || 'Terjadi kesalahan yang tidak diketahui'); } // Tampilkan hasil originalContentEl.value = data.originalContent; decryptedContentEl.value = data.decryptedContent; resultSection.classList.remove('hidden'); } catch (err) { // Tampilkan error errorBox.textContent = 'Error: ' + err.message; errorBox.classList.remove('hidden'); } finally { // UI state: Idle submitButton.disabled = false; spinner.classList.add('hidden'); buttonText.textContent = 'Dekripsi'; } }); </script> </body> </html> `; } --1f04fff558f595c26b2b166dbe8ca9919f2463ff35dc17e8d25fe0224976--
Bindings
Tambah KV
Tambah R2
Tambah D1
← Kembali
Simpan & Deploy
Hapus Script Worker Ini