Hai, teman-teman! Kali ini masalahnya kebalikan dari bagian-bagian sebelumnya. Kalau di bagian 7 kita mengisi database toko dengan data palsu dari nol, kali ini datanya sudah asli. Ada laporan penjualan yang angkanya aneh, dan tim yang memperbaikinya butuh salinan data pelanggan untuk mencari penyebabnya. Masalahnya, data itu berisi nama, email, dan nomor telepon orang sungguhan, dan tidak boleh keluar begitu saja.
Ide pertama yang terpikir: ganti saja semua nama dan email dengan data palsu dari Faker. Setelah diganti, laporannya dijalankan ulang:
Sebelum disamarkan, transaksi tersambung: 5000 dari 5000
Sesudah disamarkan, transaksi tersambung: 28 dari 5000
Datanya memang sudah tersamar, tapi 4.972 transaksi kehilangan pemiliknya, dan laporannya jadi tidak bisa dipakai sama sekali. Di bagian terakhir seri ini, kita belajar anonimisasi data dengan Python dan Faker yang konsisten: nilai asli yang sama selalu berubah menjadi nilai palsu yang sama, sehingga relasi antartabel tetap utuh.
![]() |
| Faker Python Series bagian 8, bagian terakhir: menyamarkan data asli tanpa memutus relasi |
TL;DR: Mengganti setiap sel dengan nilai acak baru memutus relasi antartabel. Kamus pengganti menjaga relasi, tapi hasilnya berubah setiap kali dijalankan. Cara yang konsisten adalah menurunkan seed Faker dari HMAC-SHA256 nilai asli dengan kunci rahasia, lalu memanggil fake.seed_instance(). Jangan pakai hash() bawaan Python, karena hasilnya berbeda di setiap proses. Hasilnya secara teknis adalah pseudonimisasi, bukan anonimisasi penuh, jadi tetap perlu diperlakukan sebagai data pribadi.
![]() |
| Teknik di artikel ini termasuk pseudonimisasi: samaran masih bisa dikaitkan ke orangnya lewat kunci rahasia |
Yang Sudah Kita Pelajari
Bagian terakhir ini memakai bekal dari tiga bagian sebelumnya:
- Bagian 4:
fake.uniqueuntuk mencegah nilai kembar. - Bagian 6:
seed_instance()untuk mengatur seed satu object Faker. - Bagian 7: mengisi database toko dengan dua tabel berelasi, pelanggan dan transaksi.
Tujuan Artikel Ini
Di sini kamu akan belajar:
- Membedakan anonimisasi dan pseudonimisasi.
- Melihat kenapa penggantian acak dan kamus pengganti belum cukup.
- Membuat nilai samaran yang konsisten dengan seed dari HMAC-SHA256.
- Menyamarkan file CSV dan memastikan relasinya tetap utuh.
- Mengenali batasan teknik ini.
Kenalan Dulu: Anonimisasi atau Pseudonimisasi?
Anonimisasi berarti data diubah sampai orangnya tidak bisa dikenali lagi dengan cara apa pun. Pseudonimisasi berarti data identitas diganti dengan nilai lain, tapi masih bisa dikembalikan ke orangnya dengan bantuan informasi tambahan, misalnya kunci rahasia. Teknik di artikel ini termasuk pseudonimisasi.
Bedanya penting. Regulasi perlindungan data Uni Eropa, GDPR, mendefinisikan pseudonymisation di Pasal 4 angka 5 sebagai pemrosesan data pribadi sehingga data itu tidak bisa lagi dikaitkan ke orang tertentu tanpa informasi tambahan, dengan syarat informasi tambahan itu disimpan terpisah dan dilindungi.
Recital 26 GDPR lalu menegaskan bahwa data hasil pseudonimisasi tetap dianggap data pribadi. Hanya data yang benar-benar anonim, yang orangnya tidak bisa lagi dikenali, yang berada di luar aturan perlindungan data.
Di Indonesia, data pribadi diatur dalam Undang-Undang Nomor 27 Tahun 2022 tentang Pelindungan Data Pribadi. Menurut ringkasan di katalog peraturan BPK, data pribadi yang bersifat umum meliputi nama lengkap, jenis kelamin, kewarganegaraan, agama, status perkawinan, dan data pribadi yang dikombinasikan untuk mengidentifikasi seseorang.
Jadi file hasil artikel ini memang jauh lebih aman untuk dibagikan ke tim, tapi bukan berarti boleh disebar bebas. Artikel ini membahas tekniknya, bukan nasihat hukum. Untuk keputusan berbagi data di organisasimu, tanyakan ke bagian yang mengurus kepatuhan atau perlindungan data.
Data Contoh yang Dipakai
Supaya aman dicoba, "data asli" di artikel ini juga buatan Faker, dengan seed yang berbeda dari data samarannya. Ada dua file: pelanggan.csv berisi 1.000 pelanggan, dan transaksi.csv berisi 5.000 transaksi. Keduanya dihubungkan lewat email, seperti yang sering ditemukan di file ekspor:
{'id': 1, 'nama': 'Kezia Pangestu', 'email': 'jagaragaprayoga@gmail.com', 'telepon': '081468819736', 'kota': 'Surabaya'}
{'id': 1, 'email_pelanggan': 'bsafitri@gmail.com', 'nominal': 172000}
Kolom nama, email, dan telepon adalah identitas yang harus disamarkan. Kolom kota dan nominal dibiarkan, karena justru itu yang dibutuhkan untuk analisis.
Cara Naif: Ganti Setiap Sel dengan Nilai Acak
Cara paling sederhana adalah memanggil Faker untuk setiap sel:
for p in pelanggan:
p["nama"] = fake.name()
p["email"] = fake.free_email()
for t in transaksi:
t["email_pelanggan"] = fake.free_email()
Hasilnya sudah kita lihat di pembuka: hanya 28 dari 5.000 transaksi yang masih tersambung ke pelanggan, dan 28 itu pun hanya kebetulan email acaknya sama. Email bsafitri@gmail.com di tabel pelanggan berubah menjadi satu email palsu, sedangkan email yang sama di tabel transaksi berubah menjadi email palsu yang lain. Faker tidak tahu bahwa keduanya sebenarnya orang yang sama.
Kamus Pengganti: Konsisten, Tapi Hanya Sekali Jalan
Supaya orang yang sama selalu mendapat samaran yang sama, Faker perlu "mengingat". Cara paling langsung adalah kamus: setiap email asli dicatat bersama samarannya, dan kalau email itu muncul lagi, samaran yang sama dipakai ulang.
def buat_penyamar():
fake = Faker("id_ID")
kamus = {}
def samarkan_email(email):
if email not in kamus:
kamus[email] = fake.unique.free_email()
return kamus[email]
return samarkan_email, kamus
fake.unique dari bagian 4 dipakai supaya dua pelanggan berbeda tidak mendapat samaran yang sama. Hasilnya:
Transaksi tersambung: 5000 dari 5000
Isi kamus: 1000 pasangan
Relasinya utuh. Tapi coba lihat apa yang terjadi kalau penyamarnya dibuat ulang, seperti saat skrip dijalankan minggu depan untuk data baru:
jagaragaprayoga@gmail.com -> simanjuntakcindy@hotmail.com (jalan pertama)
jagaragaprayoga@gmail.com -> maulanaumay@hotmail.com (jalan kedua)
Pelanggan yang sama mendapat dua samaran yang berbeda. Data minggu ini dan minggu depan jadi tidak bisa digabung. Agar konsisten, kamusnya harus disimpan, dan di situ masalah baru muncul: kamus itu berisi pasangan email asli dan samarannya. Siapa pun yang memegang file kamus bisa membuka semua samaran.
Seed dari HMAC: Konsisten Tanpa Menyimpan Kamus
Ide yang lebih rapi: jangan simpan pasangan nilai asli dan samarannya, tapi turunkan seed Faker langsung dari nilai asli. Nilai asli yang sama selalu menghasilkan seed yang sama, dan Faker yang di-seed sama selalu menghasilkan nilai palsu yang sama. Kamusnya tidak perlu disimpan, karena hasilnya bisa dihitung ulang kapan saja.
Jebakan: hash() Bawaan Python Berubah Setiap Proses
Fungsi pertama yang terpikir untuk mengubah teks menjadi angka adalah hash(). Coba jalankan untuk email yang sama di dua proses Python terpisah:
hash() proses 1: 721925512769610246
hash() proses 2: 4248353738700463404
Hasilnya berbeda. Ini disengaja: sejak lama, Python mengacak hash() untuk teks di setiap proses demi keamanan, seperti dijelaskan di dokumentasi variabel PYTHONHASHSEED. Kalau kamu menjalankan skripnya, angkanya akan berbeda lagi. Jadi hash() tidak bisa dipakai sebagai dasar samaran yang konsisten.
Kenapa HMAC, Bukan SHA-256 Biasa?
SHA-256 dari modul hashlib selalu menghasilkan angka yang sama untuk teks yang sama. Tapi ada lubang. Orang yang punya daftar email kandidat bisa menghitung SHA-256 setiap email itu sendiri, lalu mencocokkannya dengan data samaran. Samarannya jadi bisa ditebak tanpa kunci apa pun.
HMAC menutup lubang itu dengan mencampurkan kunci rahasia ke dalam perhitungan. Tanpa kunci, hasil HMAC tidak bisa dihitung ulang. Kunci inilah "informasi tambahan" dalam definisi pseudonimisasi GDPR tadi, yang harus disimpan terpisah dari data samaran.
import hashlib
import hmac
import os
from faker import Faker
# kunci rahasia dibaca dari environment variable, jangan ditulis di kode
KUNCI = os.environ.get("KUNCI_SAMARAN", "contoh-kunci-jangan-dipakai").encode()
fake = Faker("id_ID")
def sidik(nilai, jenis):
"""HMAC-SHA256 dari nilai asli. `jenis` membuat nama dan email yang sama tetap beda hasil."""
return hmac.new(KUNCI, f"{jenis}:{nilai}".encode(), hashlib.sha256).digest()
def pakai_seed_dari(nilai, jenis):
fake.seed_instance(int.from_bytes(sidik(nilai, jenis)[:8], "big"))
def samarkan_nama(nama):
pakai_seed_dari(nama, "nama")
return fake.name()
def samarkan_email(email):
pakai_seed_dari(email, "email")
# 6 karakter sidik ditempel supaya dua email asli tidak jatuh ke email palsu yang sama
return f"{fake.user_name()}.{sidik(email, 'email').hex()[:6]}@example.com"
def samarkan_telepon(telepon):
pakai_seed_dari(telepon, "telepon")
return fake.numerify("08##########")
Ada beberapa hal yang perlu diperhatikan:
fake.seed_instance(), bukanFaker.seed().Faker.seed()mengatur pengacak yang dipakai bersama semua object Faker di program, sedangkanseed_instance()hanya mengatur objectfakeini. Penjelasan seed ada di dokumentasi Faker bagian Seeding the Generator.jenisikut dihitung. Tanpa itu, teks yang sama di kolom berbeda akan mendapat seed yang sama.- 8 byte pertama HMAC diubah menjadi angka bulat untuk seed. Itu sudah lebih dari cukup untuk membedakan nilai.
- Email samaran memakai domain
example.com. Domain ini dicadangkan khusus untuk contoh dan dokumentasi oleh RFC 2606, jadi tidak akan pernah terkirim ke kotak masuk orang sungguhan kalau ada sistem yang tidak sengaja mengirim email.
Hasil dua kali pemanggilan untuk nilai yang sama:
R.A. Jamalia Agustina | raharjamandasari.a505f1@example.com
R.A. Jamalia Agustina | raharjamandasari.a505f1@example.com
Sama persis, dan akan tetap sama di proses berikutnya, minggu depan, atau di komputer lain, selama kuncinya sama.
Kenapa Email Butuh Akhiran Sidik
Seed yang berbeda tetap bisa menghasilkan nama pengguna yang sama, karena daftar nama di Faker terbatas. Ini masalah yang sama dengan email kembar di bagian 4. Kita hitung untuk 1.000 email pelanggan:
Tanpa akhiran: 990 email berbeda dari 1000
Dengan akhiran: 1000 email berbeda dari 1000
Tanpa akhiran, 10 pasang pelanggan berbagi email samaran, dan transaksi mereka akan tercampur. fake.unique tidak bisa menolong di sini, karena unique bergantung pada urutan pemanggilan, sedangkan kita butuh hasil yang hanya bergantung pada nilai asli. Akhiran 6 karakter heksadesimal dari HMAC memberi lebih dari 16 juta kombinasi tambahan, dan nilainya tetap konsisten.
Menyamarkan File CSV dan Memeriksa Hasilnya
Sekarang penyamar dipakai untuk kedua file. Kolom id, kota, dan nominal tidak disentuh:
for p in pelanggan:
p["nama"] = samarkan_nama(p["nama"])
p["email"] = samarkan_email(p["email"])
p["telepon"] = samarkan_telepon(p["telepon"])
# id dan kota dibiarkan, karena dipakai untuk analisis
for t in transaksi:
t["email_pelanggan"] = samarkan_email(t["email_pelanggan"])
tulis("pelanggan_samaran.csv", pelanggan)
tulis("transaksi_samaran.csv", transaksi)
Menyamarkan tanpa memeriksa sama saja dengan berharap. Jadi hasilnya langsung diperiksa dari empat sisi:
{'id': '1', 'nama': 'Tgk. Prabowo Prakasa', 'email': 'waskitairwan.d61d5c@example.com', 'telepon': '086296319402', 'kota': 'Surabaya'}
Transaksi tersambung: 5000 dari 5000
Email samaran berbeda: 1000 dari 1000
Email asli yang tersisa: 0
Total nominal sama: True
Relasinya utuh, tidak ada email samaran yang kembar, tidak ada email asli yang tertinggal, dan angka yang dipakai untuk analisis tidak berubah. Laporan yang aneh tadi sekarang bisa diperiksa dengan data samaran, dan hasil analisisnya akan sama dengan data asli.
Batasan yang Perlu Diingat
Nama dan email yang diganti belum tentu membuat orangnya tidak bisa dikenali. Ada empat hal yang tetap perlu diwaspadai:
- Kombinasi kolom yang tersisa. Kota, pola belanja, dan tanggal transaksi, kalau digabung, kadang cukup untuk menebak seseorang. Pelanggan satu-satunya di kota kecil yang selalu belanja besar setiap Jumat tetap mudah dikenali, walaupun namanya sudah diganti. Ini sebabnya ringkasan UU PDP menyebut "data pribadi yang dikombinasikan untuk mengidentifikasi seseorang".
- Kunci rahasia adalah segalanya. Siapa pun yang memegang kunci dan daftar email kandidat bisa mencocokkan samarannya. Simpan kunci di tempat terpisah dari data samaran, jangan ditulis di kode, dan jangan ikut dikirim bersama file.
- Kolom teks bebas. Kolom catatan atau alamat bisa saja berisi nama atau nomor telepon yang diketik manual. Penyamar per kolom seperti di atas tidak akan menemukannya.
- Samaran bisa kebetulan sama dengan nama orang lain. Ini dibahas di tantangan nomor 3.
Error yang Sering Muncul Saat Menyamarkan Data dengan Faker
Kesalahan di penyamaran data jarang menampilkan error. Yang muncul justru relasi yang putus diam-diam, atau samaran yang berubah tanpa ada yang sadar.
| Gejala | Penyebab | Perbaikan |
|---|---|---|
| Transaksi kehilangan pelanggannya setelah disamarkan | Setiap sel diganti nilai acak baru | Turunkan seed dari nilai asli, supaya nilai yang sama selalu mendapat samaran yang sama |
| Samaran berubah setiap kali skrip dijalankan | Seed memakai hash() bawaan, atau penyamar memakai kamus yang tidak disimpan |
Pakai HMAC-SHA256 dengan kunci tetap |
| Dua pelanggan berbagi email samaran | Nama pengguna dari seed berbeda kebetulan sama | Tempel beberapa karakter HMAC ke email samaran |
| Samaran berbeda di komputer lain | Nilai KUNCI_SAMARAN di environment berbeda, atau tidak diisi sehingga memakai kunci contoh |
Pastikan semua yang menjalankan skrip memakai kunci yang sama dari tempat penyimpanan rahasia |
| Data dummy lain di program ikut berubah urutannya | Penyamar memakai Faker.seed() yang mengatur pengacak bersama |
Pakai fake.seed_instance() pada object Faker khusus penyamar |
Tantangan untuk Kamu
Coba kerjakan dulu sebelum membuka jawabannya. Jalankan 1_buat_data_contoh.py dan 5_samarkan_csv.py dulu supaya semua file CSV tersedia.
Tantangan 1. Buktikan bahwa kunci yang berbeda menghasilkan samaran yang berbeda untuk email yang sama.
import importlib
import os
import penyamar
print("Kunci contoh :", penyamar.samarkan_email("dlestari@hotmail.com"))
os.environ["KUNCI_SAMARAN"] = "kunci-lain"
importlib.reload(penyamar)
print("Kunci lain :", penyamar.samarkan_email("dlestari@hotmail.com"))
Kunci contoh : raharjamandasari.a505f1@example.com
Kunci lain : fputra.768e42@example.com
KUNCI dibaca sekali saat modul diimpor, jadi modulnya perlu dimuat ulang dengan importlib.reload() setelah environment variable diubah. Ini juga menunjukkan kenapa kunci harus dijaga: dengan kunci lain, seluruh samaran berubah total.
Tantangan 2. Buktikan bahwa omzet per kota dari data samaran sama persis dengan data asli.
def omzet_per_kota(file_pelanggan, file_transaksi):
kota_per_email = {p["email"]: p["kota"] for p in baca(file_pelanggan)}
omzet = Counter()
for t in baca(file_transaksi):
omzet[kota_per_email[t["email_pelanggan"]]] += int(t["nominal"])
return omzet
asli = omzet_per_kota("pelanggan.csv", "transaksi.csv")
samaran = omzet_per_kota("pelanggan_samaran.csv", "transaksi_samaran.csv")
print("Omzet per kota sama:", asli == samaran, dict(asli.most_common(2)))
Omzet per kota sama: True {'Jakarta': 320399000, 'Bandung': 150487500}
Fungsi yang sama dipakai untuk kedua pasang file. Kalau relasi email di data samaran putus, baris kota_per_email[...] akan langsung melempar KeyError.
Tantangan 3. Pastikan tidak ada nama, email, atau telepon asli yang tertinggal di file samaran.
asli_per_id = {p["id"]: p for p in baca("pelanggan.csv")}
bocor = [
(s["id"], kolom)
for s in baca("pelanggan_samaran.csv")
for kolom in ("nama", "email", "telepon")
if s[kolom] == asli_per_id[s["id"]][kolom]
]
print("Nilai asli yang tertinggal di barisnya sendiri:", len(bocor))
# kecocokan lintas baris: nilai samaran kebetulan sama dengan nilai asli milik orang lain
nilai_asli = {p[kolom]: p["id"] for p in asli_per_id.values() for kolom in ("nama", "email", "telepon")}
for s in baca("pelanggan_samaran.csv"):
for kolom in ("nama", "email", "telepon"):
if s[kolom] in nilai_asli:
print(f"Kebetulan sama: {kolom} samaran id {s['id']} = {s[kolom]!r}, nilai asli milik id {nilai_asli[s[kolom]]}")
Nilai asli yang tertinggal di barisnya sendiri: 0
Kebetulan sama: nama samaran id 880 = 'Amelia Sihombing', nilai asli milik id 593
Versi pertama jawaban ini mencari nilai asli di semua sel tanpa melihat barisnya, dan menemukan 1 kecocokan. Setelah ditelusuri, itu bukan kebocoran. Nama samaran pelanggan 880 kebetulan sama dengan nama asli pelanggan 593, karena keduanya diambil dari daftar nama yang terbatas. Data pelanggan 593 sendiri tetap tersamar. Karena itu, pemeriksaan kebocoran yang benar membandingkan per baris, sedangkan kecocokan lintas baris cukup dicatat sebagai kebetulan.
Kode lengkap ketiga jawaban ada di 6_tantangan.py di GitHub.
Penutup Seri
Delapan bagian seri ini sebenarnya bergerak ke satu arah. Di awal, Faker dipakai untuk membuat data palsu sebanyak mungkin. Di akhir, data palsu itu harus mirip data asli: punya kolom yang unik, kolom yang kosong, pola yang berbobot, NIK yang lolos validasi, relasi yang utuh, sampai bisa menggantikan identitas di data asli tanpa merusak analisisnya.
Di setiap bagian, langkah terpenting selalu sama: periksa hasilnya dengan menghitung. Email kembar, name_male() yang separuhnya perempuan, toko yang ramai jam 3 pagi, dan nama samaran yang kebetulan sama dengan pelanggan lain. Semuanya baru ketahuan setelah datanya dihitung, bukan setelah dilihat sekilas.
Daftar semua artikel seri ini ada di label Faker Python. Kalau kamu pernah harus membagikan data pelanggan ke tim lain, kolom mana yang paling sulit disamarkan: nama, alamat, atau catatan teks bebas? Ceritakan di kolom komentar, tanpa menyebut data aslinya tentu saja.
Source code lengkap artikel ini bisa dilihat di GitHub: 08-anonimisasi-data-faker
FAQ
Apa beda anonimisasi dan pseudonimisasi data? Anonimisasi mengubah data sampai orangnya tidak bisa dikenali lagi dengan cara apa pun. Pseudonimisasi mengganti identitas dengan nilai lain yang masih bisa dikembalikan dengan informasi tambahan, misalnya kunci rahasia. Menurut Recital 26 GDPR, data hasil pseudonimisasi tetap dianggap data pribadi.
Bagaimana cara menyamarkan data dengan Faker tanpa memutus relasi antartabel?
Turunkan seed Faker dari nilai asli, misalnya dengan HMAC-SHA256 dan kunci rahasia, lalu panggil fake.seed_instance() sebelum membuat nilai palsu. Nilai asli yang sama selalu menghasilkan samaran yang sama, jadi email yang sama di tabel pelanggan dan transaksi tetap tersambung.
Kenapa tidak memakai fungsi hash() bawaan Python untuk seed?
Python mengacak hasil hash() untuk teks di setiap proses demi keamanan, jadi email yang sama menghasilkan angka yang berbeda setiap kali program dijalankan. Gunakan hmac atau hashlib yang hasilnya selalu sama untuk masukan yang sama.
Kenapa harus memakai kunci rahasia saat menyamarkan data? Tanpa kunci, siapa pun yang punya daftar email kandidat bisa menghitung hash-nya sendiri dan mencocokkannya dengan data samaran. Dengan HMAC dan kunci rahasia, hasilnya tidak bisa dihitung ulang tanpa kunci. Simpan kunci terpisah dari data samaran, dan jangan menuliskannya di kode.
Apakah data yang sudah disamarkan dengan Faker boleh dibagikan bebas? Tidak otomatis. Kolom yang tersisa, seperti kota dan pola belanja, kadang masih bisa dipakai untuk mengenali seseorang kalau digabung, dan data hasil pseudonimisasi tetap tergolong data pribadi. Pastikan pembagiannya sesuai kebijakan perlindungan data di organisasimu.
Referensi
- Art. 4 GDPR Definitions, gdpr-info.eu, diakses 22 Oktober 2026
- Recital 26 GDPR, gdpr-info.eu, diakses 22 Oktober 2026
- UU Nomor 27 Tahun 2022 tentang Pelindungan Data Pribadi, JDIH BPK, diakses 22 Oktober 2026
- hmac, Dokumentasi Python, diakses 22 Oktober 2026
- PYTHONHASHSEED, Dokumentasi Python, diakses 22 Oktober 2026
- Seeding the Generator, Dokumentasi Faker, diakses 22 Oktober 2026
- RFC 2606: Reserved Top Level DNS Names, diakses 22 Oktober 2026


Posting Komentar untuk "Faker Python Series 8: Anonimisasi Data Asli secara Konsisten"