Certificate Pinning — een mechanisme om het certificaat of de openbare sleutel van de server vast te zetten, waarbij de app een vooraf bekende vingerafdruk gebruikt om de HTTPS-verbinding te verifiëren. In tegenstelling tot de standaard vertrouwensketen via CA, garandeert pinning dat zelfs een gecompromitteerde certificeringsinstantie geen vervalst certificaat voor uw domein kan uitgeven. Volgens OWASP MSTG (2025) staat Certificate Pinning op de lijst van verplichte controles voor apps met beveiligingsniveau L2. Implementatie omvat het opslaan van certificaat-hashes in de code en verificatie bij elk verzoek.
Belangrijkste punten
Certificate Pinning — is een beveiligingstechniek waarbij de app de vingerafdruk (fingerprint) van een vertrouwd certificaat opslaat en deze als enige criterium gebruikt om een HTTPS-verbinding tot stand te brengen. In het standaard TLS-model controleert de client of het servercertificaat is ondertekend door een vertrouwde root-CA — een van de honderden vooraf geïnstalleerde instanties in het systeem. Certificate Pinning vervangt deze keten door een directe controle: het certificaat moet overeenkomen met het opgeslagen exemplaar of de verwachte openbare sleutel bevatten.
Het probleem van het standaardmodel werd duidelijk na incidenten met CA-compromittering — DigiNotar (2011), Comodo (2011), TrustCor (2022). Als een CA een vervalst certificaat voor uw domein uitgeeft, accepteert de browser of app dit als geldig. Certificate Pinning voorkomt deze aanval: zelfs een perfect ondertekend vervalst certificaat wordt geweigerd, omdat de vingerafdruk niet overeenkomt met de in de app vastgezette.
De term pinning komt van pin — „pen” of ‗vastzetter”: de ontwikkelaar zet het vertrouwde certificaat vast en elke afwijking ervan blokkeert de verbinding. Volgens onderzoek van Mitre CWE-295 blijft onjuiste certificaatvalidatie een van de top-10 gevaarlijkste beveiligingsfouten in mobiele apps, en Certificate Pinning is de directe methode om dit te voorkomen.
Aanvankelijk werd Certificate Pinning in browsers gebruikt via het HPKP-mechanisme (HTTP Public Key Pinning), gestandaardiseerd in RFC 7469. De ontwikkelaar stuurde een HTTP-header Public-Key-Pins met hashes van verwachte sleutels, en de browser onthield deze voor een bepaalde periode. HPKP bleek echter gevaarlijk: één configuratiefout kon de site maandenlang blokkeren. In 2018 stopte Chrome met de ondersteuning van HPKP en nu is de standaard software-implementatie aan de clientzijde — binnen de mobiele app of browserextensie.
Het Certificate Pinning-proces omvat drie belangrijke fasen: het berekenen van de vingerafdruk, verificatie bij verbinding en foutafhandeling. In de voorbereidingsfase verkrijgt de ontwikkelaar de SHA-256-hash van het certificaat of de openbare sleutel van de productieserver. Voor GDPR- en PCI DSS-conforme apps is ook het vastzetten van vingerafdrukken van tussenliggende CA’s in de keten vereist.
Bij elk HTTPS-verzoek onderschept de app de TLS-authenticatie-callback, extraheert het servercertificaat en berekent de SHA-256-hash. Deze hash wordt vergeleken met de opgeslagen lijst van vertrouwde vingerafdrukken. Als een overeenkomst wordt gevonden — gaat de verbinding door. Zo niet — moet de app de verbinding verbreken en de fout melden, zonder implementatiedetails aan de aanvaller prijs te geven.
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
}
De functie ontvangt een X509Certificate-object van de server en de verwachte hash. Eerst wordt de openbare sleutel van het certificaat geëxtraheerd, de SHA-256-hash berekend en in Base64 gecodeerd. Het resultaat wordt vergeleken met de verwachte vingerafdruk. In productie is het zinvol om controle op een array van 2–3 vingerafdrukken toe te voegen voor rotatieondersteuning.
Bij implementatie van pinning moet worden gekozen welk cryptografisch object wordt vastgezet. Certificate Pinning koppelt aan het X.509-certificaat zelf — het serienummer, de geldigheidsperiode en de hele keten. Public Key Pinning zet alleen de openbare sleutel in het certificaat vast en negeert de andere velden. De keuze heeft aanzienlijke invloed op de operationele kosten.
| Criterium | Certificate Pinning | Public Key Pinning |
|---|---|---|
| Vastzetobject | X.509-certificaat volledig | RSA/ECDSA openbare sleutel |
| Rotatie | Vereist update bij elke heruitgifte | Verandert niet bij certificaatwijziging met dezelfde sleutel |
| Beveiliging | Maximaal precieze koppeling | Minder gevoelig voor details |
| Flexibiliteit | Laag — certificaten veranderen elke 1–2 jaar | Hoog — sleutels kunnen 5–10 jaar meegaan |
| Aanbeveling | Voor kritieke systemen met gecontroleerde updates | Voor de meeste mobiele apps en API’s |
Public Key Pinning — de voorkeurskeuze voor de meeste projecten. De openbare sleutels van servers blijven meestal ongewijzigd bij heruitgifte van het certificaat — het bedrijf ondertekent eenvoudigweg de oude sleutel met een nieuw certificaat. Dit betekent dat de app geen update nodig heeft na certificaatwijziging, als het sleutelpaar niet is veranderd. Certificate Pinning wordt aanbevolen voor scenario’s waarin de ontwikkelaar zowel de server als de clientcode volledig beheert, bijvoorbeeld in bedrijfsapps met een strikte updatecyclus.
TOFU — een strategie waarbij Certificate Pinning niet vooraf is geconfigureerd, maar het certificaat onthoudt bij de eerste verbinding met de server. Deze benadering is handig voor apps die niet van tevoren weten met welke server ze verbinding maken. Nadeel — kwetsbaarheid bij de eerste aanval: als de eerste verbinding wordt onderschept, wordt het vervalste certificaat als vertrouwd geaccepteerd. TOFU wordt gebruikt in SSH-verbindingen en sommige P2P-protocollen.
Op beide platformen wordt Certificate Pinning geïmplementeerd door TLS-verbinding op netwerkstackniveau te onderscheppen. Op iOS wordt URLSession-delegate of Alamofire ServerTrustManager gebruikt. Op Android is de voorkeursmethode OkHttp CertificatePinner, dat is ingebouwd in populaire HTTP-clients en configuratie van meerdere vingerafdrukken voor elk domein ondersteunt.
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
}
In de Swift-functie wordt uit serverTrust de certificaatketen geëxtraheerd, voor elke wordt de SHA-256-hash berekend en het resultaat vergeleken met de verwachte. Door alle certificaten in de keten te doorlopen, kan pinning op het niveau van tussenliggende CA worden geïmplementeerd — als het tussenliggende certificaat overeenkomt, wordt de verbinding geaccepteerd. Dit biedt flexibiliteit bij rotatie van leaf-certificaten.
Als de app geen OkHttp gebruikt, kan Certificate Pinning worden geïmplementeerd via een aangepaste X509TrustManager. Deze methode vereist meer code, maar geeft volledige controle over het verificatieproces. TrustManager overschrijft de methode checkServerTrusted, waar de ontwikkelaar handmatig de servercertificaten controleert en een vertrouwensbeslissing neemt. Alleen aanbevolen voor specifieke scenario’s waar de OkHttp-bibliotheek niet beschikbaar is.
De meest voorkomende fout — het ontbreken van back-uppins. De ontwikkelaar plaatst één certificaatvingerafdruk en bij verval ervan verliezen gebruikers massaal de verbinding. De minimaal acceptabele configuratie — twee vingerafdrukken: huidig certificaat en back-up. Optimaal — drie: huidig, back-up en vingerafdruk van root-CA als fallback.
De tweede fout — het opslaan van pins in open vorm in de code. Een aanvaller met toegang tot APK of IPA kan eenvoudig vingerafdrukken extraheren en vervangen. Het wordt aanbevolen om hashes te obfuscateren: de string in delen splitsen, in versleutelde bronnen opslaan of via runtime berekenen. Voor Android is ProGuard met obfuscatie van stringconstanten effectief.
De derde fout — pinning op het niveau van een ontwikkelcertificaat. Ontwikkel- en productiecertificaten zijn meestal verschillend, maar ontwikkelaars vergeten vaak de pins te wijzigen bij het bouwen van een release. Het resultaat — de productie-app kan geen verbinding maken met de server. Oplossing — aparte pinconfiguratie voor debug en release via BuildConfig of flavourspecifieke bronnen.
Veelgestelde vragen
SSL Pinning — algemene term voor koppeling aan een SSL/TLS-certificaat. Certificate Pinning — concrete implementatie die het X.509-certificaat zelf vastzet, niet alleen de openbare sleutel. Het verschil zit in het object van koppeling: certificaat vs sleutel.
Het wordt aanbevolen hashes op te slaan in bronnen met obfuscatie via ProGuard (Android) of versleuteld via Keychain (iOS). Vermijd het opslaan van pins in open vorm in strings.xml of Info.plist zonder versleuteling.
Bij elke wijziging van het certificaat op de server. Het wordt aanbevolen om 3–6 maanden voor het vervallen van het huidige certificaat een nieuwe vingerafdruk als back-uppin toe te voegen en na rotatie de oude te verwijderen. Minimaal één back-uppin is verplicht.
Ja, via voorwaardelijke compilatie: in de debug-build is pinning uitgeschakeld, in release — ingeschakeld. Gebruik BuildConfig.DEBUG op Android of #if DEBUG op iOS voor het schakelen. Doe dit nooit via een runtime-vlag die toegankelijk is voor de gebruiker.
Breng onmiddellijk een app-update uit met nieuwe vingerafdrukken en publiceer deze in de stores. Gebruik een geforceerd updatemechanisme. Als de back-uppins de vingerafdruk van een reserve-CA bevatten, kan tijdelijk worden overgeschakeld naar een ander domein met een ander certificaat.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook