Hash function — SHA-256 & Keccak-256
Sebelum menyentuh Solidity sekalipun, kamu perlu paham satu operasi yang dipakai di hampir setiap baris data on-chain: hash. Bukan enkripsi, bukan kompresi — fungsi satu arah yang mengubah data sebesar apa pun jadi string tetap.
Intisari
- Hash itu satu arah (tidak bisa dibalik), deterministik (input sama → output sama selalu), dan panjang keluarannya tetap berapa pun ukuran inputnya.
- Ethereum memakai Keccak-256, bukan SHA3-256 standar NIST — meski keduanya sering disebut tertukar. Paddingnya beda, hasilnya beda.
- Avalanche effect: ubah satu bit input, sekitar separuh bit output ikut berubah. Ini yang membuat hash berguna untuk deteksi perubahan data sekecil apa pun.
- Address akun Ethereum diturunkan dari hash public key — bukan angka acak yang didaftarkan ke server mana pun.
- Solidity:
keccak256(abi.encodePacked(...))adalah pola yang sangat umum, tapiencodePackedpunya jebakan collision kalau kamu tidak hati-hati.
Bukan enkripsi — jangan tertukar
Pendatang dari dunia Web2 sering menyamakan hash dengan enkripsi. Bedanya mendasar: enkripsi bisa dibalik (dengan kunci yang benar), hash tidak bisa. Begitu data di-hash, tidak ada operasi apa pun — termasuk oleh pembuatnya sendiri — yang mengembalikan input asli dari outputnya.
| Sifat | Artinya | Kenapa penting di blockchain |
|---|---|---|
| Satu arah (one-way) | Tidak ada fungsi balik dari hash ke input | Password/private key bisa direpresentasikan tanpa membocorkan aslinya |
| Deterministik | Input sama selalu hasil sama | Semua node bisa memverifikasi hasil yang sama, tanpa koordinasi |
| Panjang tetap | Input 1 byte atau 1 GB, output tetap 32 byte (Keccak-256) | Header block bisa merepresentasikan jutaan transaksi dalam ukuran konstan |
| Avalanche effect | 1 bit input berubah → ~50% bit output berubah | Tidak ada pola yang bisa ditebak dari perubahan kecil |
| Collision-resistant | Sangat sulit menemukan dua input beda dengan hash sama | Hash bisa dipercaya sebagai "sidik jari" data |
SHA-256 vs Keccak-256 — jebakan penamaan
Ini yang paling sering membingungkan orang yang datang dari dunia backend biasa. Bitcoin memakai
SHA-256 (standar NIST, FIPS 180-4). Ethereum memakai fungsi yang di Solidity dipanggil
keccak256 — dan ini bukan SHA3-256 yang juga distandarkan NIST (FIPS 202).
Ceritanya: Keccak adalah pemenang kompetisi SHA-3 milik NIST. Tapi sebelum distandarkan resmi, NIST mengubah
skema padding-nya. Ethereum sudah lebih dulu mengadopsi Keccak versi asli (pra-standardisasi), jadi
keccak256(x) di Solidity menghasilkan nilai berbeda dari sha3_256(x)
di pustaka kriptografi modern mana pun — meski algoritmanya nyaris identik.
Kalau kamu memverifikasi hash on-chain dari luar (Java/PHP), pastikan pustaka yang kamu pakai
eksplisit menyediakan varian "Keccak" — bukan "SHA3". Di Java, ini berarti Bouncy Castle dengan digest
"KECCAK-256", bukan "SHA3-256" dari java.security bawaan. Hash yang
"hampir benar" akan lolos compile, lolos type-check, dan menghasilkan alamat atau selector yang salah tanpa
satu pun error.
Ke mana saja Keccak-256 dipakai di Ethereum
| Dipakai untuk | Caranya |
|---|---|
| Address akun | 20 byte terakhir dari keccak256(public_key) |
| Function selector | 4 byte pertama dari keccak256("transfer(address,uint256)") |
| Event topic | keccak256 dari signature event, jadi topic pertama di log |
| Storage slot mapping | keccak256(key . slot) menentukan lokasi nilai mapping |
| Merkle Patricia Trie | Setiap node trie diidentifikasi oleh hash kontennya sendiri |
Memakai keccak256 di Solidity
// Menghitung function selector secara manual — inilah yang membuat
// ABI encoding "hanya" soal mencocokkan 4 byte pertama data transaksi.
bytes4 selector = bytes4(keccak256("transfer(address,uint256)"));
// Pola umum: hash gabungan beberapa nilai untuk jadi kunci unik
function buatId(address pemilik, uint256 nomor) public pure returns (bytes32) {
return keccak256(abi.encodePacked(pemilik, nomor));
}
Jebakan abi.encodePacked. Fungsi ini menggabungkan byte tanpa padding maupun
pemisah. Akibatnya encodePacked("ab", "c") menghasilkan byte yang sama persis
dengan encodePacked("a", "bc") — dua pasangan dinamis (string/bytes) yang berbeda tapi hash-nya
identik. Kalau kamu menghitung hash dari lebih dari satu nilai bertipe dinamis, pakai
abi.encode (dengan padding) untuk mencegah collision jenis ini.
Menghitung hash dari luar rantai (Java & PHP)
Backend yang memverifikasi data on-chain sering perlu menghitung hash yang sama secara independen — misalnya memverifikasi bahwa payload yang ditandatangani belum diubah sebelum dikirim sebagai transaksi.
import org.web3j.crypto.Hash;
import org.web3j.utils.Numeric;
// web3j sudah menyediakan Keccak-256 yang BENAR — bukan SHA3-256 bawaan JDK
byte[] data = "halo dunia".getBytes();
String hashHex = Numeric.toHexString(Hash.sha3(data));
// Ekstensi kriptografi bawaan PHP (openssl, hash()) TIDAK punya Keccak-256 —
// hash('sha3-256', ...) di PHP adalah SHA3 standar NIST, bukan Keccak Ethereum.
// Perlu pustaka khusus, misalnya kornrunner/keccak:
$keccak = new \kornrunner\Keccak();
$hashHex = $keccak::hash('halo dunia', 256);
Latihan: hitung keccak256("transfer(address,uint256)") lewat Remix (fungsi
pure sederhana), lalu bandingkan 4 byte pertamanya dengan selector yang muncul di tab
"Method ID" saat kamu memanggil fungsi transfer token ERC-20 mana pun di Etherscan. Keduanya
harus identik — itulah yang membuat node tahu fungsi mana yang kamu panggil hanya dari data mentah transaksi.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.