Certificate Pinning — mekanisme pengikatan sertifikat atau kunci publik server, di mana aplikasi menggunakan sidik jari yang sudah diketahui sebelumnya untuk memverifikasi koneksi HTTPS. Berbeda dengan rantai kepercayaan standar melalui CA, pinning menjamin bahwa bahkan pusat sertifikasi yang dikompromikan pun tidak dapat menerbitkan sertifikat palsu untuk domain Anda. Menurut OWASP MSTG (2025), Certificate Pinning termasuk dalam daftar kontrol wajib untuk aplikasi dengan tingkat perlindungan L2. Implementasi mencakup penyimpanan hash sertifikat dalam kode dan verifikasi pada setiap permintaan.
Poin Utama
Certificate Pinning — adalah teknik keamanan di mana aplikasi menyimpan sidik jari (fingerprint) sertifikat tepercaya dan menggunakannya sebagai satu-satunya kriteria untuk membuat koneksi HTTPS. Dalam model TLS standar, klien memeriksa apakah sertifikat server ditandatangani oleh root CA tepercaya — salah satu dari ratusan pusat yang sudah diinstal sebelumnya di sistem. Certificate Pinning menggantikan rantai ini dengan pemeriksaan langsung: sertifikat harus cocok dengan sampel yang disimpan atau berisi kunci publik yang diharapkan.
Masalah model standar menjadi jelas setelah insiden kompromi CA — DigiNotar (2011), Comodo (2011), TrustCor (2022). Jika CA menerbitkan sertifikat palsu untuk domain Anda, browser atau aplikasi menerimanya sebagai valid. Certificate Pinning mencegah serangan ini: bahkan sertifikat palsu yang ditandatangani sempurna akan ditolak, karena sidik jarinya tidak cocok dengan yang diikat dalam aplikasi.
Istilah pinning berasal dari pin — “peniti” atau “pengikat”: pengembang mengikat sertifikat tepercaya, dan setiap penyimpangan darinya memblokir koneksi. Menurut penelitian Mitre CWE-295, validasi sertifikat yang tidak benar tetap menjadi salah satu dari 10 kesalahan keamanan paling berbahaya dalam aplikasi mobile, dan Certificate Pinning adalah metode langsung untuk mencegahnya.
Awalnya Certificate Pinning digunakan di browser melalui mekanisme HPKP (HTTP Public Key Pinning), yang distandarisasi dalam RFC 7469. Pengembang mengirimkan header HTTP Public-Key-Pins dengan hash kunci yang diharapkan, dan browser mengingatnya untuk periode tertentu. Namun HPKP terbukti berbahaya: satu kesalahan konfigurasi dapat memblokir situs selama berbulan-bulan. Pada tahun 2018, Chrome menghentikan dukungan untuk HPKP, dan sekarang standarnya adalah implementasi perangkat lunak di sisi klien — di dalam aplikasi mobile atau ekstensi browser.
Proses Certificate Pinning mencakup tiga tahap kunci: menghitung sidik jari, verifikasi saat koneksi, dan penanganan kesalahan. Pada tahap persiapan, pengembang mendapatkan hash SHA-256 dari sertifikat atau kunci publik server produksi. Untuk aplikasi yang sesuai dengan GDPR dan PCI DSS, juga diperlukan untuk mengikat sidik jari CA perantara dalam rantai.
Pada setiap permintaan HTTPS, aplikasi mencegat callback autentikasi TLS, mengekstrak sertifikat server, dan menghitung hash SHA-256-nya. Hash ini dibandingkan dengan daftar sidik jari tepercaya yang disimpan. Jika kecocokan ditemukan — koneksi dilanjutkan. Jika tidak — aplikasi harus memutus koneksi dan melaporkan kesalahan, tanpa mengungkapkan detail implementasi kepada penyerang.
fun validateCertificate(certificate: X509Certificate,
expectedHash: String): Boolean {
val digest = MessageDigest.getInstance("SHA-256")
val hash = Base64.encodeToString(
digest.digest(certificate.publicKey.getEncoded()),
Base64.DEFAULT
).trim()
return hash == expectedHash
}
Fungsi menerima objek X509Certificate dari server dan hash yang diharapkan. Pertama, kunci publik sertifikat diekstrak, hash SHA-256 dihitung, dan dikodekan dalam Base64. Hasilnya dibandingkan dengan sidik jari yang diharapkan. Dalam produksi, ada baiknya menambahkan pemeriksaan pada array 2–3 sidik jari untuk mendukung rotasi.
Saat mengimplementasikan pinning, perlu dipilih objek kriptografi mana yang akan diikat. Certificate Pinning mengikat ke sertifikat X.509 itu sendiri — nomor seri, masa berlaku, dan seluruh rantainya. Public Key Pinning hanya mengikat kunci publik di dalam sertifikat, mengabaikan bidang lainnya. Pilihan secara signifikan mempengaruhi biaya operasional.
| Kriteria | Certificate Pinning | Public Key Pinning |
|---|---|---|
| Objek pengikatan | Sertifikat X.509 secara keseluruhan | Kunci publik RSA/ECDSA |
| Rotasi | Memerlukan pembaruan setiap kali diterbitkan ulang | Tidak berubah saat sertifikat berubah dengan kunci yang sama |
| Keamanan | Pengikatan paling presisi | Kurang sensitif terhadap detail |
| Fleksibilitas | Rendah — sertifikat berubah setiap 1–2 tahun | Tinggi — kunci dapat bertahan 5–10 tahun |
| Rekomendasi | Untuk sistem kritis dengan pembaruan terkontrol | Untuk sebagian besar aplikasi mobile dan API |
Public Key Pinning — pilihan yang lebih disukai untuk sebagian besar proyek. Kunci publik server biasanya tetap tidak berubah saat sertifikat diterbitkan ulang — perusahaan cukup menandatangani kunci lama dengan sertifikat baru. Ini berarti aplikasi tidak memerlukan pembaruan setelah perubahan sertifikat, jika pasangan kunci tidak berubah. Certificate Pinning direkomendasikan untuk skenario di mana pengembang mengontrol penuh baik server maupun kode klien, misalnya, dalam aplikasi perusahaan dengan siklus pembaruan yang ketat.
TOFU — strategi di mana Certificate Pinning tidak dikonfigurasi sebelumnya, tetapi mengingat sertifikat pada koneksi pertama dengan server. Pendekatan ini nyaman untuk aplikasi yang tidak tahu sebelumnya server mana yang akan mereka hubungi. Kekurangannya — kerentanan terhadap serangan pertama: jika koneksi pertama dicegat, sertifikat palsu akan diterima sebagai tepercaya. TOFU diterapkan dalam koneksi SSH dan beberapa protokol P2P.
Di kedua platform, Certificate Pinning diimplementasikan dengan mencegat koneksi TLS di tingkat tumpukan jaringan. Di iOS, digunakan delegat URLSession atau Alamofire ServerTrustManager. Di Android, metode yang lebih disukai adalah OkHttp CertificatePinner, yang terintegrasi dalam klien HTTP populer dan mendukung konfigurasi beberapa sidik jari untuk setiap domain.
func validate(serverTrust: SecTrust,
pinnedHash: String) -> Bool {
guard let certificates = SecTrustCopyCertificateChain(serverTrust)
as? [SecCertificate] else { return false }
for certificate in certificates {
let data = SecCertificateCopyData(certificate)
var hash = Data(repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
data.withUnsafeBytes {
CC_SHA256($0.baseAddress,
CC_LONG(data.count), &hash)
}
if hash.base64EncodedString() == pinnedHash {
return true
}
}
return false
}
Dalam fungsi Swift, dari serverTrust diekstrak rantai sertifikat, untuk masing-masing dihitung hash SHA-256, dan hasilnya dibandingkan dengan yang diharapkan. Melintasi semua sertifikat dalam rantai memungkinkan implementasi pinning di tingkat CA perantara — jika sertifikat perantara cocok, koneksi diterima. Ini memberikan fleksibilitas dalam rotasi sertifikat leaf.
Jika aplikasi tidak menggunakan OkHttp, Certificate Pinning dapat diimplementasikan melalui X509TrustManager kustom. Metode ini membutuhkan lebih banyak kode, tetapi memberikan kontrol penuh atas proses verifikasi. TrustManager menimpa metode checkServerTrusted, di mana pengembang secara manual memeriksa sertifikat server dan membuat keputusan tentang kepercayaan. Hanya direkomendasikan untuk skenario spesifik di mana pustaka OkHttp tidak tersedia.
Kesalahan paling umum — tidak adanya pin cadangan. Pengembang menempatkan satu sidik jari sertifikat, dan saat kedaluwarsa, pengguna kehilangan koneksi secara massal. Konfigurasi minimum yang dapat diterima — dua sidik jari: sertifikat saat ini dan cadangan. Optimal — tiga: saat ini, cadangan, dan sidik jari root CA sebagai fallback.
Kesalahan kedua — menyimpan pin dalam bentuk terbuka di kode. Penyerang dengan akses ke APK atau IPA dapat dengan mudah mengekstrak dan mengganti sidik jari. Disarankan untuk melakukan obfuskasi hash: membagi string menjadi beberapa bagian, menyimpannya dalam sumber daya terenkripsi, atau menghitungnya melalui runtime. Untuk Android, ProGuard dengan obfuskasi konstanta string efektif.
Kesalahan ketiga — pinning di tingkat sertifikat pengembangan. Sertifikat pengembangan dan produksi biasanya berbeda, tetapi pengembang sering lupa mengganti pin saat membangun rilis. Hasilnya — aplikasi produksi tidak dapat terhubung ke server. Solusi — konfigurasi pin terpisah untuk debug dan rilis melalui BuildConfig atau sumber daya spesifik flavour.
Pertanyaan yang Sering Diajukan
SSL Pinning — istilah umum untuk pengikatan ke sertifikat SSL/TLS. Certificate Pinning — implementasi konkret yang mengikat sertifikat X.509 itu sendiri, bukan hanya kunci publik. Perbedaannya terletak pada objek pengikatan: sertifikat vs kunci.
Disarankan untuk menyimpan hash dalam sumber daya dengan obfuskasi melalui ProGuard (Android) atau dienkripsi melalui Keychain (iOS). Hindari menyimpan pin dalam bentuk terbuka di strings.xml atau Info.plist tanpa enkripsi.
Setiap kali sertifikat di server berubah. Disarankan untuk menambahkan sidik jari baru sebagai pin cadangan 3–6 bulan sebelum kedaluwarsa sertifikat saat ini, dan setelah rotasi menghapus yang lama. Setidaknya satu pin cadangan wajib.
Ya, melalui kompilasi bersyarat: di build debug pinning dinonaktifkan, di rilis — diaktifkan. Gunakan BuildConfig.DEBUG di Android atau #if DEBUG di iOS untuk peralihan. Jangan pernah melakukan ini melalui flag runtime yang dapat diakses pengguna.
Segera rilis pembaruan aplikasi dengan sidik jari baru dan publikasikan di toko. Gunakan mekanisme pembaruan paksa. Jika pin cadangan menyertakan sidik jari CA cadangan, untuk sementara dapat beralih ke domain lain dengan sertifikat lain.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga