Certificate Pinning — mechanismus fixace certifikátu nebo veřejného klíče serveru, při kterém aplikace používá předem známý otisk pro ověření HTTPS spojení. Na rozdíl od standardního řetězce důvěry prostřednictvím CA, pinning zaručuje, že ani kompromitovaná certifikační autorita nebude moci vydat falešný certifikát pro vaši doménu. Podle OWASP MSTG (2025) je Certificate Pinning na seznamu povinných kontrol pro aplikace úrovně ochrany L2. Implementace zahrnuje ukládání hashů certifikátů v kódu a ověřování při každém požadavku.
Hlavní body
Certificate Pinning — bezpečnostní technika, při které aplikace ukládá otisk (fingerprint) důvěryhodného certifikátu a používá jej jako jediné kritérium pro navázání HTTPS spojení. Ve standardním modelu TLS klient kontroluje, zda je certifikát serveru podepsán důvěryhodnou kořenovou CA — kteroukoliv ze stovek předinstalovaných autorit v systému. Certificate Pinning nahrazuje tento řetězec přímou kontrolou: certifikát se musí shodovat s uloženým vzorkem nebo obsahovat očekávaný veřejný klíč.
Problém standardního modelu se stal zřejmým po incidentech kompromitace CA — DigiNotar (2011), Comodo (2011), TrustCor (2022). Pokud CA vydá falešný certifikát pro vaši doménu, prohlížeč nebo aplikace jej přijme jako platný. Certificate Pinning tomuto útoku brání: i dokonale podepsaný falešný certifikát bude odmítnut, protože jeho otisk neodpovídá tomu fixovanému v aplikaci.
Termín pinning pochází z pin — „špendlík“ nebo „ fixátor“: vývojář fixuje důvěryhodný certifikát a jakákoli odchylka od něj blokuje spojení. Podle výzkumu Mitre CWE-295 zůstává nesprávná validace certifikátů jednou z top-10 nejnebezpečnějších bezpečnostních chyb v mobilních aplikacích a Certificate Pinning je přímou metodou její prevence.
Původně byl Certificate Pinning používán v prohlížečích prostřednictvím mechanismu HPKP (HTTP Public Key Pinning), standardizovaného v RFC 7469. Vývojář odesílal HTTP hlavičku Public-Key-Pins s hashi očekávaných klíčů a prohlížeč si je pamatoval po stanovenou dobu. HPKP se však ukázal jako nebezpečný: jedna chyba v konfiguraci mohla zablokovat web na měsíce. V roce 2018 Chrome ukončil podporu HPKP a nyní je standardem softwarová implementace na straně klienta — uvnitř mobilní aplikace nebo rozšíření prohlížeče.
Proces Certificate Pinning zahrnuje tř9i klíčové fáze: výpočet otisku, ověření při připojení a zpracování chyby. Ve fázi přípravy vývojář získá SHA-256 hash certifikátu nebo veřejného klíče produkčního serveru. Pro aplikace vyhovující GDPR a PCI DSS je také nutné fixovat otisky prostředních CA v řetězci.
Při každém HTTPS požadavku aplikace zachytí callback autentizace TLS, extrahuje certifikát serveru a vypočítá jeho SHA-256 hash. Tento hash je porovnán s uloženým seznamem důvěryhodných otisků. Pokud je nalezena shoda — spojení pokračuje. Pokud ne — aplikace musí přerušit spojení a ohlásit chybu, aniž by prozradila detaily implementace útočníkovi.
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
}
Funkce přijímá objekt X509Certificate od serveru a očekávaný hash. Nejprve se extrahuje veřejný klíč certifikátu, vypočítá se SHA-256 hash a zakóduje se do Base64. Výsledek se porovná s očekávaným otiskem. V produkci stojí za to přidat kontrolu na pole 2–3 otisků pro podporu rotace.
Při implementaci pinningu je třeba zvolit, který kryptografický objekt fixovat. Certificate Pinning se váže na samotný certifikát X.509 — jeho sériové číslo, dobu platnosti a celý řetězec. Public Key Pinning fixuje pouze veřejný klíč uvnitř certifikátu, ignorujíc ostatní pole. Volba významně ovlivňuje provozní náklady.
| Kritérium | Certificate Pinning | Public Key Pinning |
|---|---|---|
| Objekt fixace | Certifikát X.509 celý | Veřejný klíč RSA/ECDSA |
| Rotace | Vyžaduje aktualizaci při každém novém vydání | Nemění se při změně certifikátu se stejným klíčem |
| Bezpečnost | Maximálně přesné vázání | Méně citlivé na detaily |
| Flexibilita | Nízká — certifikáty se mění každý 1–2 roky | Vysoká — klíče mohou žít 5–10 let |
| Doporučení | Pro kritické systémy s řízenými aktualizacemi | Pro většinu mobilních aplikací a API |
Public Key Pinning — preferovaná volba pro většinu projektů. Veřejné klíče serverů obvykle zůstávají nezměněny při novém vydání certifikátu — společnost jednoduše podepíše starý klíč novým certifikátem. To znamená, že aplikace nevyžaduje aktualizaci po změně certifikátu, pokud se pár klíčů nezměnil. Certificate Pinning se doporučuje pro scénáře, kde vývojář plně kontroluje jak server, tak klientský kód, například v podnikových aplikacích s přísným cyklem aktualizací.
TOFU — strategie, při které Certificate Pinning není předem nakonfigurován, ale pamatuje si certifikát při prvním připojení k serveru. Tento přístup je vhodný pro aplikace, které předem nevědí, ke kterému serveru se připojí. Nevýhoda — zranitelnost při prvním útoku: pokud je první spojení zachyceno, falešný certifikát bude přijat jako důvěryhodný. TOFU se používá v SSH připojeních a některých P2P protokolech.
Na obou platformách je Certificate Pinning implementován zachycením TLS spojení na úrovni síťového zásobníku. Na iOS se používá delegát URLSession nebo Alamofire ServerTrustManager. Na Android je preferovaným způsobem OkHttp CertificatePinner, který je integrován v populárních HTTP klientech a podporuje konfiguraci více otisků pro každou doménu.
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
}
Ve funkci Swift je ze serverTrust extrahován řetězec certifikátů, pro každý je vypočítán SHA-256 hash a výsledek porovnán s očekávaným. Průchod všemi certifikáty v řetězci umožňuje implementovat pinning na úrovni prostřední CA — pokud se prostřední certifikát shoduje, spojení je přijato. To poskytuje flexibilitu při rotaci leaf certifikátů.
Pokud aplikace nepoužívá OkHttp, lze Certificate Pinning implementovat prostřednictvím vlastního X509TrustManager. Tato metoda vyžaduje více kódu, ale poskytuje úplnou kontrolu nad procesem ověřování. TrustManager přepisuje metodu checkServerTrusted, kde vývojář ručně kontroluje certifikáty serveru a rozhoduje o důvěře. Doporučuje se pouze pro specifické scénáře, kde knihovna OkHttp není k dispozici.
Nejčastější chyba — chybějící záložní piny. Vývojář umístí jeden otisk certifikátu a při jeho vypršení uživatelé hromadně ztrácejí spojení. Minimálně přijatelná konfigurace — dva otisky: aktuální certifikát a záložní. Optimální — tři: aktuální, záložní a otisk kořenové CA jako fallback.
Druhá chyba — ukládání pinů v otevřené podobě v kódu. Útočník s přístupem k APK nebo IPA může snadno extrahovat a nahradit otisky. Doporučuje se obfuskace hashů: rozdělit řetězec na části, ukládat v šifrovaných zdrojích nebo počítat za běhu. Pro Android je účinný ProGuard s obfuskací řetězcových konstant.
Třetí chyba — pinning na úrovni development certifikátu. Vývojové a produkční certifikáty jsou obvykle odlišné, ale vývojáři často zapomínají přepnout piny při sestavování release. Výsledek — produkční aplikace se nemůže připojit k serveru. Řešení — oddělená konfigurace pinů pro debug a release pomocí BuildConfig nebo prostředků specifických pro flavour.
Často kladené otázky
SSL Pinning — obecný termín pro vázání na SSL/TLS certifikát. Certificate Pinning — konkrétní implementace, která fixuje samotný certifikát X.509, nejen veřejný klíč. Rozdíl je v objektu fixace: certifikát vs klíč.
Doporučuje se ukládat hashe ve zdrojích s obfuskací pomocí ProGuard (Android) nebo šifrovaně pomocí Keychain (iOS). Vyhněte se ukládání pinů v otevřené podobě v strings.xml nebo Info.plist bez šifrování.
Při každé změně certifikátu na serveru. Doporučuje se přidání nového otisku jako záložního pin 3–6 měsíců před vypršením aktuálního a po rotaci odstranění starého. Minimálně jeden záložní pin je povinný.
Ano, pomocí podmíněné kompilace: v debug sestavení je pinning vypnutý, v release — zapnutý. Použijte BuildConfig.DEBUG na Android nebo #if DEBUG na iOS pro přepínání. Nikdy to nedělejte pomocí runtime příznaku přístupného uživateli.
Okamžitě vydat aktualizaci aplikace s novými otisky a publikovat ji v obchodech. Použít mechanismus vynucené aktualizace. Pokud záložní piny zahrnovaly otisk záložní CA, dočasně lze přejít na jinou doménu s jiným certifikátem.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také