On this page+
"Tenang, password kamu dienkripsi di database kami."
Kalimat kayak gini sering banget muncul, padahal hampir selalu salah. Password yang disimpan dengan benar itu di-hash, bukan dienkripsi. Dua-duanya memang mengubah data jadi deretan karakter acak, makanya gampang ketukar. Tapi tujuannya beda jauh, dan salah pilih bisa berujung data bocor.
Versi singkatnya: encryption buat data yang nanti perlu dibaca lagi, hashing buat data yang cukup dicocokkan saja.
Hashing: jalan satu arah#
Hashing mengubah input sepanjang apa pun jadi output dengan panjang tetap, biasa disebut hash atau digest. Mau inputnya satu kata atau file 4 GB, hasil SHA-256 tetap 64 karakter hex.
Sifat pentingnya ada empat:
Satu arah. Dari hash, nggak ada jalan balik ke data aslinya.
Konsisten. Input yang sama selalu menghasilkan hash yang sama.
Sensitif. Beda satu karakter saja, hasilnya berubah total.
Tanpa kunci. Siapa pun bisa menghitung hash dari data yang sama.
Coba lihat bedanya halo dan Halo di SHA-256:
halo -> a4e63bcacf6c172ad84f9f4523c8f1acaf33676fa76d3258c67b7e7bbf16d777
Halo -> 4e86512d9a0af8a743d42a1a0f3eaee0945790ddb79c8db14309337c1235b2e4Cuma beda huruf besar di depan, tapi hasilnya sama sekali nggak mirip.
Di Node.js, bikinnya cukup satu baris:
const crypto = require("crypto");
const hash = crypto.createHash("sha256").update("halo").digest("hex");Analogi yang paling pas itu sidik jari. Sidik jari bisa dipakai buat memastikan ini orang yang sama, tapi nggak bisa dipakai buat "membangun ulang" orangnya.
Hashing biasa dipakai untuk menyimpan password, mengecek file hasil download nggak rusak atau diubah (checksum), ID commit di Git, dan tanda tangan digital.
Encryption: dikunci, bisa dibuka lagi#
Encryption mengubah data asli (plaintext) jadi data acak (ciphertext) pakai kunci. Bedanya dengan hashing: siapa pun yang pegang kunci yang benar bisa mengembalikannya ke bentuk semula.
Ada dua jenis:
Simetris. Satu kunci untuk mengunci dan membuka. Cepat, cocok untuk data besar. Contohnya AES dan ChaCha20.
Asimetris. Sepasang kunci: public key untuk mengunci, private key untuk membuka. Lebih lambat, tapi kamu nggak perlu kirim kunci rahasia ke siapa-siapa. Contohnya RSA dan ECC.
Praktiknya dua-duanya sering dipakai bareng. HTTPS pakai asimetris di awal untuk sepakat soal kunci, lalu lanjut simetris untuk datanya.
Contoh AES-256-GCM di Node.js:
const crypto = require("crypto");
const key = crypto.randomBytes(32); // simpan baik-baik, jangan di repo
const iv = crypto.randomBytes(12); // wajib baru setiap kali enkripsi
// kunci
const cipher = crypto.createCipheriv("aes-256-gcm", key, iv);
const encrypted = Buffer.concat([cipher.update("halo", "utf8"), cipher.final()]);
const tag = cipher.getAuthTag();
// buka
const decipher = crypto.createDecipheriv("aes-256-gcm", key, iv);
decipher.setAuthTag(tag);
const plain = Buffer.concat([decipher.update(encrypted), decipher.final()]).toString("utf8");
// "halo"Analoginya brankas. Isinya aman selama kuncinya aman, dan begitu kuncinya jatuh ke orang lain, isinya ikut terbuka. Makanya di encryption, yang paling susah bukan algoritmanya tapi cara menyimpan kuncinya.
Encryption dipakai di HTTPS, chat end-to-end, enkripsi disk, dan data sensitif di database yang memang perlu ditampilkan lagi seperti nomor rekening atau alamat.
Bedanya sekilas#
Kondisi | Hashing | Encryption |
|---|---|---|
Arah | Satu arah | Dua arah |
Kunci | Nggak ada | Ada |
Panjang hasil | Selalu tetap | Ikut panjang datanya |
Tujuan | Memastikan data cocok atau nggak berubah | Menjaga data tetap rahasia |
Algoritma | SHA-256, bcrypt, Argon2 | AES, ChaCha20, RSA |
Contoh pakai | Password, checksum file | HTTPS, chat, enkripsi disk |
Kapan pakai yang mana#
Cukup tanya satu hal: nanti saya perlu lihat data aslinya lagi atau nggak?
Kalau perlu, pakai encryption. Nomor HP user yang ditampilkan di halaman profil, token API pihak ketiga yang harus dikirim ulang, file backup, semuanya harus bisa dibuka lagi.
Kalau cukup dicocokkan, pakai hashing. Waktu user login, kamu nggak perlu tahu passwordnya apa. Kamu cuma perlu hash dari yang dia ketik, lalu bandingkan dengan hash yang tersimpan. Kalau sama, berarti passwordnya benar.
Khusus password ada satu catatan:
jangan pakai SHA-256 polos
SHA-256 dirancang supaya cepat, dan itu justru masalah, karena GPU bisa mencoba miliaran tebakan per detik. Pakai algoritma yang memang dibuat untuk password seperti bcrypt atau Argon2. Dua-duanya sengaja lambat dan otomatis menambahkan salt.
const bcrypt = require("bcrypt");
const hash = await bcrypt.hash(password, 12); // saat daftar
const cocok = await bcrypt.compare(input, hash); // saat loginKesalahan yang sering kejadian#
Mengenkripsi password. Begitu kuncinya bocor, semua password user terbuka sekaligus. Kalau di-hash, penyerang masih harus menebak satu per satu.
Masih pakai MD5 atau SHA-1 untuk password. Dua-duanya sudah lama dianggap nggak aman, dan sama-sama terlalu cepat.
Hash tanpa salt. Salt itu nilai acak yang ditambahkan ke tiap password sebelum di-hash. Tanpa salt, dua user dengan password sama punya hash yang sama, dan penyerang bisa pakai tabel hash yang sudah jadi (rainbow table).
Mengira Base64 itu enkripsi. Base64 cuma encoding. Nggak ada kuncinya, siapa pun bisa decode.
Menyimpan kunci enkripsi di repo atau di database yang sama dengan datanya. Itu sama saja menaruh kunci brankas di atas brankasnya.
Percaya situs "decrypt MD5". Hash nggak bisa di-decrypt. Situs begitu cuma mencocokkan hash kamu dengan daftar raksasa hasil hash password-password umum. Kalau password kamu ketemu di sana, artinya passwordnya terlalu pasaran.
Penutup#
Hashing dan encryption bukan saingan, dan di satu aplikasi biasanya dua-duanya kepakai. Password di-hash, koneksinya dienkripsi lewat HTTPS, data sensitif di database dienkripsi lagi.
Jadi kalau lain kali ada yang bilang "password kamu kami enkripsi", semoga itu cuma salah istilah.
Did this help you? Say thanks.
