Encoding, hashing, dan encryption sering tertukar karena sama-sama mengubah data jadi bentuk lain yang gak terbaca. Tapi tujuannya beda jauh. Bayangin tiga hal: menerjemahkan tulisan ke kode Morse (siapa pun bisa balik), mencap sidik jari di atas dokumen (gak bisa dibalik jadi orangnya), dan mengunci surat di brankas (cuma yang punya kunci bisa buka). Encoding itu Morse, hashing itu sidik jari, encryption itu brankas.
🧪 Tebakan cepat: kamu menyimpan password user. Mana yang tepat: encoding, hashing, atau encryption? Dan kalau kamu salah memilih encryption, apa bahayanya? Tebak dulu, jawabannya ada di bagian "Memilih yang tepat".
Encoding: ganti format, bukan keamanan
Encoding mengubah format data supaya bisa ditransfer atau disimpan dengan aman di jalur teks. Siapa pun bisa meng-encode, dan siapa pun bisa meng-decode. Gak ada kunci, gak ada rahasia. Contoh paling umum Base64:
const encoded = btoa("Halo"); // "SGFsbw=="
const decoded = atob("SGFsbw=="); // "Halo"
btoameng-encode teks ke Base64,atobmembalikkannya. Keduanya function bawaan browser.- Hasilnya
"SGFsbw=="bukan rahasia: siapa pun yang punya string itu bisaatobdan dapat "Halo" lagi. - Dipakai untuk: mengirim data biner lewat JSON, menaruh gambar kecil di URL (
data:), danencodeURIComponentuntuk karakter di URL.
Base64 bukan keamanan. Meng-encode password dengan Base64 itu seperti menulis password di kertas lalu melipatnya: terlihat beda, tapi siapa pun bisa membukanya.
Hashing: satu arah, untuk sidik jari data
Hashing mengubah data apa pun jadi string berukuran tetap, dan gak bisa dikembalikan ke bentuk asli (one-way). Input yang sama selalu menghasilkan hash yang sama; ubah satu huruf, seluruh hash berubah total. Contoh SHA-256:
// SHA-256 di browser, lewat Web Crypto API
const data = new TextEncoder().encode("Halo");
const buf = await crypto.subtle.digest("SHA-256", data);
const hex = [...new Uint8Array(buf)].map((b) => b.toString(16).padStart(2, "0")).join("");
// "4e86512d9a0af8a743d42a1a0f3eaee0945790ddb79c8db1..."
crypto.subtle.digest("SHA-256", ...)menghitung hash SHA-256 yang asli di browser.- Hasilnya selalu 64 karakter hex (256 bit), entah input-nya satu huruf atau satu buku.
- Gak ada
undigest: dari hash kamu gak bisa mendapatkan "Halo" kembali.
Dipakai untuk: verifikasi integritas file (checksum), dan membandingkan dua data tanpa menyimpan aslinya. Tapi SHA-256 terlalu cepat untuk password: penyerang bisa mencoba miliaran tebakan per detik. Untuk password pakai hash lambat khusus, bcrypt atau argon2, yang sengaja dibikin pelan dan pakai salt.
Encryption: dua arah, butuh kunci
Encryption mengubah data jadi ciphertext yang cuma bisa dibaca lagi dengan kunci yang benar (two-way). Ini untuk kerahasiaan data yang nanti perlu dibaca. Contoh AES-GCM, enkripsi simetris (satu kunci untuk kunci dan buka):
// Buat kunci acak dan nonce (angka sekali-pakai)
const key = await crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
const iv = crypto.getRandomValues(new Uint8Array(12));
const pesan = new TextEncoder().encode("data rahasia");
const cipher = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, pesan);
const balik = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, cipher);
// new TextDecoder().decode(balik) === "data rahasia"
generateKeymembuat kunci AES-256 acak.encryptmengubah pesan jadi ciphertext yang terlihat acak.decryptdengan kunci danivyang sama mengembalikan pesan asli. Salah kunci? Gagal, bukan hasil yang salah diam-diam.iv(nonce) harus baru tiap enkripsi. Mengulang iv dengan kunci yang sama membocorkan pola.
Encryption asymmetric (RSA) pakai dua kunci: public key untuk mengunci, private key untuk membuka. Inilah yang dipakai di TLS untuk menyepakati kunci.
Memilih yang tepat
| Kebutuhan | Pakai | Kenapa |
|---|---|---|
| Menyimpan password | hashing (bcrypt/argon2) | gak perlu dibaca lagi, cukup dicocokkan |
| Data rahasia yang perlu dibaca lagi | encryption (AES) | bisa di-decrypt dengan kunci |
| Kirim data biner lewat teks | encoding (Base64) | cuma soal format, bukan rahasia |
| Verifikasi integritas file | hashing (SHA-256) | sidik jari yang cepat dibandingkan |
Untuk password, jawabannya hashing. Kenapa bukan encryption? Karena encryption bisa di-decrypt: kalau kunci bocor, semua password terbuka sekaligus. Hashing gak bisa dibalik, jadi walau database bocor, password asli tetap tersembunyi. Itu jawaban tebakannya.
💡 Certificate pinning
Terkait TLS, ada teknik ekstra bernama certificate pinning: aplikasi menolak koneksi kalau certificate server gak cocok dengan yang sudah di-hardcode (di-pin) di dalam aplikasi. Tujuannya mengalahkan penyadap yang memakai CA jahat. Normalnya browser percaya ratusan CA; dengan pinning, penyerang tetap butuh kunci yang benar. Paling umum di mobile app, dan sebaiknya selalu pin minimal dua kunci (primer + cadangan) supaya rotasi kunci gak bikin semua user offline.
⚠️ Jebakan yang sering ketemu
- Meng-encode password dengan Base64. Itu bukan proteksi sama sekali. Siapa pun bisa
atob. - Meng-encrypt password. Kalau kunci bocor, semua password terbuka. Password harus di-hash, bukan di-encrypt.
- Memakai MD5 atau SHA biasa untuk password. Terlalu cepat, rentan brute force. Pakai bcrypt atau argon2.
- Meng-hash data yang masih perlu dibaca. Hash gak bisa dibalik. Kalau perlu dibaca lagi, itu encryption, bukan hashing.
TL;DR: Encoding (Base64) mengubah format, dua arah, tanpa kunci, bukan keamanan: siapa pun bisa atob. Hashing (SHA-256, bcrypt) satu arah, tanpa kunci, untuk sidik jari dan integritas: gak bisa dibalik. Encryption (AES, RSA) dua arah, butuh kunci, untuk kerahasiaan data yang perlu dibaca lagi. Password pakai hashing lambat (bcrypt/argon2), bukan encryption, karena kunci yang bocor membuka semua password sekaligus. Base64 untuk password itu salah besar. Certificate pinning adalah teknik ekstra yang menolak certificate yang gak cocok dengan yang di-pin.