Certificate Pinning — механизам фиксације сертификата или јавног кључа сервера, при чему апликација користи унапред познати отисак за проверу HTTPS везе. За разлику од стандардног ланца поверења преко CA, pinning гарантује да чак и компромитовани центар за сертификацију не може издати лажни сертификат за ваш домен. Према OWASP MSTG (2025), Certificate Pinning се налази на листи обавезних контрола за апликације нивоа заштите L2. Имплементација укључује чување хешева сертификата у коду и проверу при сваком захтеву.
Главне тачке
Certificate Pinning — сигурносна техника у којој апликација чува отисак (fingerprint) поузданог сертификата и користи га као једини критеријум за успостављање HTTPS везе. У стандардном TLS моделу клијент проверава да ли је сертификат сервера потписан од стране поузданог коренског CA — било ког од стотина унапред инсталираних центара у систему. Certificate Pinning замењује овај ланац директном провером: сертификат мора да се поклапа са сачуваним узорком или да садржи очекивани јавни кључ.
Проблем стандардног модела постао је очигледан након инцидената са компромитовањем CA — DigiNotar (2011), Comodo (2011), TrustCor (2022). Ако CA изда лажни сертификат за ваш домен, прегледач или апликација га прихвата као важећи. Certificate Pinning спречава овај напад: чак и савршено потписан лажни сертификат биће одбијен, јер се његов отисак не поклапа са фиксираним у апликацији.
Термин pinning потиче од pin — „клин“ или „фиксатор“: програмер фиксира поуздани сертификат, а свако одступање од њега блокира везу. Према истраживању Mitre CWE-295, неправилна валидација сертификата остаје једна од top-10 најопаснијих безбедносних грешака у мобилним апликацијама, а Certificate Pinning је директна метода њеног спречавања.
Првобитно се Certificate Pinning користио у прегледачима кроз механизам HPKP (HTTP Public Key Pinning), стандардизован у RFC 7469. Програмер је слао HTTP заглавље Public-Key-Pins са хешевима очекиваних кључева, а прегледач их је памтио на одређени период. Међутим, HPKP се показао опасним: једна грешка у конфигурацији могла је блокирати сајт месецима. Године 2018. Chrome је престао да подржава HPKP, а сада је стандард програмска имплементација на страни клијента — унутар мобилне апликације или екстензије прегледача.
Процес Certificate Pinning-а укључује три кључне фазе: израчунавање отиска, проверу при повезивању и обраду грешке. У фази припреме, програмер добија SHA-256 хеш сертификата или јавног кључа продукционог сервера. За апликације усаглашене са GDPR и PCI DSS, такође је потребно фиксирати отиске посредних CA у ланцу.
При сваком HTTPS захтеву, апликација пресреће callback аутентификације TLS, издваја сертификат сервера и израчунава његов SHA-256 хеш. Овај хеш се пореди са сачуваном листом поузданих отисака. Ако се поклапање пронађе — веза се наставља. Ако не — апликација мора прекинути везу и пријавити грешку, не откривајући детаље имплементације нападачу.
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
}
Функција прима X509Certificate објекат од сервера и очекивани хеш. Прво се издваја јавни кључ сертификата, израчунава SHA-256 хеш и кодира у Base64. Резултат се пореди са очекиваним отиском. У продукцији вреди додати проверу по низу од 2–3 отиска за подршку ротације.
При имплементацији pinning-а потребно је изабрати који криптографски објекат фиксирати. Certificate Pinning се везује за сам X.509 сертификат — његов серијски број, период важења и цео ланац. Public Key Pinning фиксира само јавни кључ унутар сертификата, игноришући остала поља. Избор значајно утиче на оперативне трошкове.
| Критеријум | Certificate Pinning | Public Key Pinning |
|---|---|---|
| Објекат фиксације | X.509 сертификат у целини | Јавни кључ RSA/ECDSA |
| Ротација | Захтева ажурирање при сваком поновном издавању | Не мења се при промени сертификата са истим кључем |
| Безбедност | Максимално прецизно везивање | Мање осетљив на детаље |
| Флексибилност | Ниска — сертификати се мењају сваких 1–2 године | Висока — кључеви могу трајати 5–10 година |
| Препорука | За критичне системе са контролисаним ажурирањима | За већину мобилних апликација и API-ја |
Public Key Pinning — пожељан избор за већину пројеката. Јавни кључеви сервера обично остају непромењени при поновном издавању сертификата — компанија једноставно потписује стари кључ новим сертификатом. То значи да апликација не захтева ажурирање након промене сертификата, ако се пар кључева није променио. Certificate Pinning се препоручује за сценарије у којима програмер потпуно контролише и сервер и клијентски код, на пример, у корпоративним апликацијама са строгим циклусом ажурирања.
TOFU — стратегија у којој Certificate Pinning није унапред конфигурисан, већ памти сертификат при првој вези са сервером. Овај приступ је погодан за апликације које унапред не знају са којим сервером ће се повезати. Недостатак — рањивост при првом нападу: ако је прва веза пресретнута, лажни сертификат ће бити прихваћен као поуздан. TOFU се примењује у SSH везама и неким P2P протоколима.
На обе платформе, Certificate Pinning се имплементира пресретањем TLS везе на нивоу мрежног стека. На iOS-у се користи URLSession делегат или Alamofire ServerTrustManager. На Android-у, пожељан начин је OkHttp CertificatePinner, који је уграђен у популарне HTTP клијенте и подржава конфигурацију више отисака за сваки домен.
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
}
У Swift функцији, из serverTrust-а се издваја ланац сертификата, за сваки се израчунава SHA-256 хеш, а резултат се пореди са очекиваним. Пролазак кроз све сертификате у ланцу омогућава имплементацију pinning-а на нивоу посредног CA — ако се посредни сертификат поклапа, веза се прихвата. Ово пружа флексибилност при ротацији leaf сертификата.
Ако апликација не користи OkHttp, Certificate Pinning се може имплементирати путем прилагођеног X509TrustManager-а. Овај метод захтева више кода, али пружа потпуну контролу над процесом провере. TrustManager преписује метод checkServerTrusted, где програмер ручно проверава сертификате сервера и доноси одлуку о поверењу. Препоручује се само за специфичне сценарије у којима библиотека OkHttp није доступна.
Најчешћа грешка — недостатак резервних отисака. Програмер поставља један отисак сертификата, а при његовом истеку корисници масовно губе везу. Минимално прихватљива конфигурација — два отиска: тренутни сертификат и резервни. Оптимално — три: тренутни, резервни и отисак коренског CA као fallback.
Друга грешка — чување отисака у отвореном облику у коду. Нападач са приступом APK-у или IPA-у може лако издвојити отиске и заменити их. Препоручује се обфускација хешева: поделити низ на делове, чувати у ресурсима са шифровањем или израчунавати кроз runtime. За Android је ефикасан ProGuard са обфускацијом низовних константи.
Трећа грешка — pinning на нивоу development сертификата. Развојни и продукциони сертификати су обично различити, али програмери често забораве да пребаце отиске при изради release верзије. Резултат — продукциона апликација не може да се повеже са сервером. Решење — одвојена конфигурација отисака за debug и release кроз BuildConfig или flavour-специфичне ресурсе.
Често постављана питања
SSL Pinning — општи термин за везивање за SSL/TLS сертификат. Certificate Pinning — конкретна имплементација која фиксира сам X.509 сертификат, а не само јавни кључ. Разлика је у објекту везивања: сертификат vs кључ.
Препоручује се чување хешева у ресурсима са обфускацијом кроз ProGuard (Android) или шифрованих кроз Keychain (iOS). Избегавајте чување отисака у отвореном облику у strings.xml или Info.plist без шифровања.
При свакој промени сертификата на серверу. Препоручује се додавање новог отиска као резервног pin-а 3–6 месеци пре истека тренутног, а након ротације уклањање старог. Минимално један резервни pin је обавезан.
Да, кроз условну компилацију: у debug верзији pinning је искључен, у release — укључен. Користите BuildConfig.DEBUG на Android-у или #if DEBUG на iOS-у за пребацивање. Никада то не радите кроз runtime флаг доступан кориснику.
Одмах објавити ажурирање апликације са новим отисцима и објавити га у продавницама. Користити механизам присилног ажурирања. Ако су резервни отисци укључивали отисак резервног CA, привремено се може прећи на други домен са другим сертификатом.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође