Oracle
Demo edukasi yang membaca pesan terenkripsi tanpa kunci, hanya dari jawaban ya atau tidak sebuah server

- panggilan oracle untuk memulihkan satu blok
- ~2.000
- komponen kriptografi ditulis dari nol
- 5
- API jaringan di aplikasi hasil build
- 0
- dependensi runtime, React dan renderer-nya
- 2
Di halaman ini
Masalahnya
Banyak orang, termasuk engineer, percaya bahwa "sudah dienkripsi dengan AES" berarti pesannya aman. Kenyataannya tidak begitu. Serangan yang sudah lama didokumentasikan, padding oracle, bisa memulihkan seluruh pesan terenkripsi tanpa membobol cipher-nya. Serangan ini hanya butuh server yang memberi tahu apakah padding sebuah pesan valid. Satu jawaban ya atau tidak, ditanyakan sekitar 2.000 kali per blok, sudah cukup untuk menyusun ulang teksnya.
Penjelasan tentang serangan ini ada di puluhan tempat, tapi jarang mengubah keyakinan orang. Satu halaman aljabar tidak membuat pembaca merasa bahwa AES-nya tidak relevan. Kebanyakan animasi yang ada juga melewatkan pengecekan positif palsu yang dibutuhkan serangan ini. Banyak pula yang diam-diam menyimpan jawabannya di sebuah variabel lalu memutarnya kembali.
Saya membuat Oracle untuk engineer yang perlu memahami kenapa enkripsi terautentikasi itu ada, untuk pengajar keamanan yang butuh demo langsung, dan untuk siapa pun yang ingin menilai apakah saya bisa mengimplementasikan kriptografi dengan benar.
Ini demo edukasi, bukan alat serangan. Aplikasinya tidak punya kode jaringan sama sekali. Sebuah tes memindai bundle hasil build dan menggagalkan build kalau ada API jaringan di dalamnya, jadi ketidakmampuannya menyerang server sungguhan adalah sifat dari build itu sendiri.
Yang saya bangun
Rahasianya saya kunci di tempat yang tak terjangkau layar
Satu modul membuat kunci, pesan, dan blok awal, mengenkripsinya, lalu hanya menyerahkan empat hal: teks terenkripsi, blok awal, oracle ya-atau-tidak, dan penghitung panggilan. Kunci dan pesannya tidak pernah keluar dari modul itu. Jadi saat huruf yang dipulihkan muncul di layar, huruf itu memang hasil serangan. Sebuah tes menyimpan pesan yang sudah diketahui di ruang tertutupnya sendiri, menjalankan serangan asli, lalu mencocokkan byte hasilnya. Aplikasi ini membuktikan bahwa ia tidak curang.
Oracle hanya menjawab satu bit
Oracle menerima pesan terenkripsi dan mengembalikan benar atau salah. Tidak ada detail error, tidak ada info waktu, tidak ada petunjuk byte mana yang gagal. Jawaban yang lebih kaya akan membuat serangannya curang dan tidak mencerminkan apa yang dilihat penyerang sungguhan. Jadi serangannya bekerja dari satu bit, sama seperti aslinya.
Pengecekan positif palsu saya bangun, dan pembaca boleh mematikannya
Saat memulihkan byte terakhir sebuah blok, serangan yang naif bisa menerima kecocokan kebetulan dan mencatat byte yang salah. Semua byte sesudahnya ikut rusak. Perbaikannya adalah mengubah byte sebelumnya lalu bertanya lagi. Saya mengimplementasikannya dan menganimasikannya sebagai langkah tersendiri. Pembaca bisa mematikannya dan melihat pemulihannya rusak. Sebuah tes memastikan versi naif memang gagal pada pesan yang dibuat untuk memicunya.
Serangan dijalankan sekali, lalu rekamannya diputar ulang
Mesin serangannya tidak memuat kode antarmuka dan tidak memakai jam. Seluruh serangan selesai dalam hitungan milidetik dan merekam setiap tebakan, setiap putusan oracle, setiap pengecekan ulang, dan hitungan di balik setiap byte. Layar hanya menampilkan satu titik di rekaman itu. Menggeser maju-mundur tidak memakan biaya, kecepatan animasi lepas dari perhitungan, dan setiap momen bisa dibagikan sebagai tautan.
Kriptografinya saya tulis sendiri
AES-128, SHA-256, HMAC, mode CBC, dan padding PKCS7 semuanya kode saya sendiri, dicek dengan vektor uji resmi. Dependensi runtime-nya hanya React dan renderer DOM-nya. Rencana awal memakai modul AES yang sudah dikompilasi. Saya membatalkannya karena kode tulisan sendiri tidak butuh file biner untuk diaudit dan tidak butuh pengecualian dari aturan tanpa jaringan.
Hasilnya
Oracle sudah live dan terbuka untuk umum. Tampilan utamanya adalah tumpukan byte empat baris: yang dikirim penyerang, padding yang dinilai oracle, blok tengah, dan teks hasil pemulihan yang terisi dari kanan ke kiri dengan warna emas. Sebuah sakelar menukar AES asli dengan cipher mainan yang diberi label jelas, dan serangannya memulihkan teks yang sama dengan biaya yang sama. Kalau encrypt-then-MAC dinyalakan, setiap pesan palsu gagal sebelum didekripsi, sehingga warna emas tidak pernah muncul.
Mode kedua mengubah "user=guest" menjadi "user=admin" di pesan terenkripsi tanpa kunci. Pemulihan butuh sekitar 2.000 panggilan oracle per blok, sesuai rata-rata teoretisnya. Saya membangunnya dalam tujuh hari pada September 2026.
Di balik layarDetail teknis untuk engineer
src/engine/secret.tsmengembalikanAttackTarget(ciphertext, IV, oracle, penghitung panggilan). Tipe ini tidak punya fieldkeyatauplaintext, danindex.tsdi engine hanya mengekspor permukaan untuk serangan.tests/view-blindness.test.tsmenjalankan serangan terhadap plaintext yang disimpan di closure milik tes.type Oracle = (ciphertext: Uint8Array) => boolean.- Disambiguasi: kalau plaintext berakhir dengan
0x02,… 02 02hasil rekayasa juga padding yang valid. Serangan mengubah byte kedua dari belakang lalu bertanya ulang.tests/disambiguation.test.tsmemastikan jalur naif gagal pada plaintext yang berakhir0x02. Sakelarnya?dis=0. - Engine-nya murni dan sinkron, tanpa import apa pun, bahkan
Date. PRNG dengan seed (src/engine/rng.ts) membuat setiap sesi bisa diulang dari URL; posisi dari tautan lama dijepit ke timeline yang dibangun. - AES-128 sekitar 230 baris (
src/engine/aes.ts), dikunci dengan vektor uji FIPS-197, sekitar 7,5 KB kode sumber. PRD awalnya meminta AES teraudit yang dikompilasi ke WebAssembly. - CI menjalankan typecheck, lint, test, build, lalu grep yang gagal kalau
fetch,XMLHttpRequest,WebSocket, atausendBeaconmuncul di bundle, baru kemudian deploy ke GitHub Pages. - Tumpukan awalnya tiga baris dan mendapat baris keempat (padding yang sebenarnya dinilai oracle) di tengah pengerjaan. Grafik batang di panel cipher dibuang dan diganti dua angka.
- Perbaikan aksesibilitas: pintasan Space memblokir Space di setiap tombol (WCAG 2.1.1); tablist tanpa tabpanel diganti tombol dengan
aria-pressed(WCAG 4.1.2); pintasan satu huruff/rdihapus (WCAG 2.1.4). Satu-satunya animasi SMIL, yang lolos dari pengaturan reduced motion, dibuang. Kontras minimal 4,5:1, ekspor hex/tabel untuk setiap byte yang dipulihkan. - State memakai React context dan reducer buatan sendiri; animasi satu loop
requestAnimationFrame; CSS polos (~2.080 baris). - Sekitar 128 panggilan oracle per byte. Ukuran halaman ~73 KB gzip dari anggaran 250 KB.
- 43 tes di 11 file. ~3.560 baris TypeScript. 65 commit di
main(68 di semua ref), 5 sampai 11 September 2026.
Tangkapan layar
Sedang merekrut, atau membangun hal serupa?
Saya terbuka untuk posisi full-time dan proyek freelance tertentu.