Apa itu SHA-256?
SHA-256 adalah singkatan dari Secure Hash Algorithm 256-bit, dan merupakan bagian dari keluarga fungsi hash kriptografi SHA-2 yang dirancang oleh NSA dan dipublikasikan pada tahun 2001. Fungsi ini mengambil input (atau 'pesan') dan mengembalikan nilai hash 256-bit (32-byte) berukuran tetap, yang biasanya ditampilkan sebagai angka heksadesimal 64 karakter.
Cara Kerja SHA-256: Penjelasan Teknis yang Mendalam
Untuk memahami SHA-256, diperlukan pemahaman beberapa lapisan operasi kriptografi. Mari kita bahas prosesnya langkah demi langkah.
1. Pra-pemrosesan (Padding)
Sebelum hashing, pesan diberi padding untuk memastikan panjangnya merupakan kelipatan 512 bit (ukuran blok untuk SHA-256). Padding terdiri dari:
- Satu bit '1'
- Cukup bit '0' untuk mendekati panjang yang diinginkan
- Representasi 64-bit dari panjang pesan asli
Ini memastikan bahwa pesan dengan panjang yang berbeda akan selalu menghasilkan hash yang berbeda, meskipun isinya mirip.
2. Pemrosesan Blok Pesan
Pesan yang dipadding dibagi menjadi blok 512-bit. Setiap blok melewati 64 putaran pemrosesan menggunakan komponen berikut:
3. Fungsi Kompresi
Inti dari SHA-256 adalah fungsi kompresinya, yang menggunakan:
- Delapan variabel kerja (a-h) diinisialisasi dari nilai hash saat ini
- Enam puluh empat konstanta (K₀ hingga K₆₃) yang diturunkan dari bagian pecahan akar pangkat tiga 64 bilangan prima pertama
- Empat fungsi logika:
Ch(x, y, z) = (x AND y) XOR (NOT x AND z) Maj(x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z) Σ₀(x) = ROTR²(x) XOR ROTR¹³(x) XOR ROTR²²(x) Σ₁(x) = ROTR⁶(x) XOR ROTR¹¹(x) XOR ROTR²⁵(x)
4. Nilai Hash Akhir
Setelah semua blok diproses, delapan variabel kerja digabungkan dengan nilai hash awal untuk (melalui penambahan modulo 2³²) untuk menghasilkan hash akhir 256-bit.
Menerapkan SHA-256: Contoh Praktis
Berikut ini adalah implementasi Python yang menunjukkan operasi inti (meskipun dalam praktiknya, kamu harus selalu menggunakan pustaka yang telah teruji seperti hashlib):
import math
def sha256(message):
# Initialize hash values (first 32 bits of fractional parts of square roots of first 8 primes)
h0 = 0x6a09e667
h1 = 0xbb67ae85
h2 = 0x3c6ef372
h3 = 0xa54ff53a
h4 = 0x510e527f
h5 = 0x9b05688c
h6 = 0x1f83d9ab
h7 = 0x5be0cd19
# Initialize round constants (first 32 bits of fractional parts of cube roots of first 64 primes)
k = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
# ... (truncated for brevity)
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]
# Pre-processing (padding)
original_length = len(message) * 8
message += b'\x80'
while (len(message) * 8 + 64) % 512 != 0:
message += b'\x00'
message += original_length.to_bytes(8, 'big')
# Process message in 512-bit chunks
for chunk in [message[i:i+64] for i in range(0, len(message), 64)]:
# Prepare message schedule
w = [0] * 64
w[0:16] = [int.from_bytes(chunk[i:i+4], 'big') for i in range(0, 64, 4)]
for i in range(16, 64):
s0 = right_rotate(w[i-15], 7) ^ right_rotate(w[i-15], 18) ^ (w[i-15] >> 3)
s1 = right_rotate(w[i-2], 17) ^ right_rotate(w[i-2], 19) ^ (w[i-2] >> 10)
w[i] = (w[i-16] + s0 + w[i-7] + s1) & 0xFFFFFFFF
# Initialize working variables
a, b, c, d, e, f, g, h = h0, h1, h2, h3, h4, h5, h6, h7
# Compression function main loop
for i in range(64):
S1 = right_rotate(e, 6) ^ right_rotate(e, 11) ^ right_rotate(e, 25)
ch = (e & f) ^ ((~e) & g)
temp1 = (h + S1 + ch + k[i] + w[i]) & 0xFFFFFFFF
S0 = right_rotate(a, 2) ^ right_rotate(a, 13) ^ right_rotate(a, 22)
maj = (a & b) ^ (a & c) ^ (b & c)
temp2 = (S0 + maj) & 0xFFFFFFFF
h = g
g = f
f = e
e = (d + temp1) & 0xFFFFFFFF
d = c
c = b
b = a
a = (temp1 + temp2) & 0xFFFFFFFF
# Add the compressed chunk to the current hash value
h0 = (h0 + a) & 0xFFFFFFFF
h1 = (h1 + b) & 0xFFFFFFFF
h2 = (h2 + c) & 0xFFFFFFFF
h3 = (h3 + d) & 0xFFFFFFFF
h4 = (h4 + e) & 0xFFFFFFFF
h5 = (h5 + f) & 0xFFFFFFFF
h6 = (h6 + g) & 0xFFFFFFFF
h7 = (h7 + h) & 0xFFFFFFFF
# Produce the final hash value
return (h0.to_bytes(4, 'big') + h1.to_bytes(4, 'big') + h2.to_bytes(4, 'big') +
h3.to_bytes(4, 'big') + h4.to_bytes(4, 'big') + h5.to_bytes(4, 'big') +
h6.to_bytes(4, 'big') + h7.to_bytes(4, 'big'))
def right_rotate(value, amount):
return (value >> amount) | (value << (32 - amount)) & 0xFFFFFFFF
Properti SHA-256
SHA-256 menunjukkan beberapa properti kriptografi penting:
- Deterministik: Input yang sama selalu menghasilkan output yang sama
- Komputasi cepat: Hash dapat dihitung dengan cepat untuk ukuran input apa pun
- Resistensi pra-gambar: Tidak mungkin untuk menentukan input dari nilai hash-nya
- Perubahan kecil seperti longsoran: Membalikkan satu bit mengubah ~50% bit output
- Tahan benturan: Tidak mungkin menemukan dua input berbeda dengan hash yang sama
Aplikasi di Dunia Nyata
SHA-256 telah menjadi hal yang umum dalam komputasi modern:
1. Teknologi Rantai Blok
Bitcoin dan banyak mata uang kripto lainnya menggunakan SHA-256 untuk:
- Penambangan (proof-of-work)
- Verifikasi transaksi
- Pembuatan alamat
2. Tanda Tangan Digital
Dikombinasikan dengan kriptografi asimetris (seperti RSA atau ECDSA), SHA-256 digunakan untuk:
- Menandatangani paket perangkat lunak
- Mengautentikasi dokumen digital
- Memverifikasi integritas pesan
3. Penyimpanan Kata Sandi
Meskipun tidak ideal jika berdiri sendiri (perlu penambahan garam dan peregangan), SHA-256 sering kali menjadi bagian dari algoritma hashing kata sandi seperti PBKDF2.
Pertimbangan Keamanan
Meskipun SHA-256 tetap aman untuk sebagian besar aplikasi, ada beberapa pertimbangan penting:
- Serangan perluasan panjang: SHA-256 rentan terhadap serangan ini tanpa konstruksi HMAC yang tepat
- Ancaman kuantum: Algoritme Grover secara teoritis dapat mengurangi keamanan hingga 128 bit
- Perangkat keras tujuan khusus: ASIC dapat menghitung SHA-256 dengan sangat cepat (penting untuk ketahanan terhadap serangan brute-force)
Melihat ke Depan: SHA-3 dan Selanjutnya
Meskipun SHA-256 tetap aman, NIST memilih Keccak sebagai SHA-3 pada tahun 2015. Keluarga SHA-3 menggunakan konstruksi spons yang sama sekali berbeda, yang menyediakan keragaman jika SHA-2 dikompromikan. Namun, SHA-256 terus mendominasi penggunaan di dunia nyata karena:
- Implementasi dan pengoptimalan yang luas
- Dukungan akselerasi perangkat keras
- Integrasi sistem yang ada
Kesimpulan
Setelah dua dekade berkecimpung di bidang ini, SHA-256 berdiri sebagai salah satu primitif kriptografi paling andal yang kita miliki. Desainnya yang cermat, margin keamanan yang konservatif, dan adopsi yang luas menjadikannya pilihan utama untuk sebagian besar kebutuhan hashing. Sementara kriptografer terus mengembangkan algoritme baru (seperti keluarga SHA-3 dan kandidat kriptografi pascakuantum), SHA-256 kemungkinan akan tetap menjadi dasar selama bertahun-tahun mendatang.
Untuk sistem baru, rekomendasi saya tetap: gunakan SHA-256 dengan konstruksi yang tepat (HMAC untuk autentikasi penandatanganan pesan, PBKDF2 atau Argon2 untuk kata sandi), awasi perkembangan kriptografi, dan selalu ikuti prinsip pertahanan berlapis.