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، اعتبارسنجی نادرست گواهی یکی از ۱۰ اشتباه امنیتی خطرناک در برنامههای موبایل باقی مانده است و Certificate Pinning روش مستقیم جلوگیری از آن است.
در ابتدا Certificate Pinning در مرورگرها از طریق مکانیزم HPKP (HTTP Public Key Pinning) استفاده میشد که در RFC 7469 استاندارد شده بود. توسعهدهنده هدر HTTP Public-Key-Pins را با هشهای کلیدهای مورد انتظار ارسال میکرد و مرورگر آنها را برای مدت مشخصی ذخیره میکرد. با این حال HPKP خطرناک بود: یک اشتباه در پیکربندی میتوانست سایت را برای ماهها مسدود کند. در سال ۲۰۱۸ کروم پشتیبانی از 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 کدگذاری میشود. نتیجه با اثر انگشت مورد انتظار مقایسه میشود. در محیط تولید، افزودن بررسی روی آرایهای از ۲–۳ اثر انگشت برای پشتیبانی از چرخش مفید است.
در پیادهسازی pinning باید انتخاب کرد که کدام شیء رمزنگاری تثبیت شود. Certificate Pinning به خود گواهی X.509 — شماره سریال، مدت اعتبار و کل زنجیره آن متصل میشود. Public Key Pinning فقط کلید عمومی داخل گواهی را تثبیت میکند و سایر فیلدها را نادیده میگیرد. انتخاب تأثیر قابل توجهی بر هزینههای عملیاتی دارد.
| معیار | Certificate Pinning | Public Key Pinning |
|---|---|---|
| شیء تثبیت | کل گواهی X.509 | کلید عمومی RSA/ECDSA |
| چرخش | نیاز به بهروزرسانی در هر بار صدور مجدد دارد | با تغییر گواهی با همان کلید تغییر نمیکند |
| امنیت | اتصال حداکثر دقیق | کمتر به جزئیات حساس است |
| انعطافپذیری | کم — گواهیها هر ۱–۲ سال تغییر میکنند | بالا — کلیدها میتوانند ۵–۱۰ سال عمر کنند |
| توصیه | برای سیستمهای حیاتی با بهروزرسانیهای کنترل شده | برای بیشتر برنامههای موبایل و API |
Public Key Pinning — انتخاب ترجیحی برای بیشتر پروژهها. کلیدهای عمومی سرورها معمولاً در هنگام صدور مجدد گواهی بدون تغییر میمانند — شرکت به سادگی کلید قدیمی را با گواهی جدید امضا میکند. این بدان معناست که اگر جفت کلید تغییر نکرده باشد، برنامه پس از تغییر گواهی نیازی به بهروزرسانی ندارد. Certificate Pinning برای سناریوهایی توصیه میشود که توسعهدهنده هم سرور و هم کد کلاینت را کاملاً کنترل میکند، مثلاً در برنامههای سازمانی با چرخه بهروزرسانی سخت.
TOFU — استراتژی که در آن Certificate Pinning از قبل پیکربندی نمیشود، بلکه گواهی را در اولین اتصال به سرور ذخیره میکند. این رویکرد برای برنامههایی مناسب است که از قبل نمیدانند به کدام سرور متصل خواهند شد. نقطه ضعف — آسیبپذیری در حمله اول: اگر اولین اتصال رهگیری شود، گواهی جعلی به عنوان معتبر پذیرفته میشود. TOFU در اتصالات SSH و برخی پروتکلهای P2P استفاده میشود.
در هر دو پلتفرم، Certificate Pinning از طریق رهگیری اتصال TLS در سطح پشته شبکه پیادهسازی میشود. در iOS از delegate 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 میتواند به راحتی اثر انگشتها را استخراج و جایگزین کند. توصیه میشود هشها مبهمسازی شوند: تقسیم رشته به بخشها، ذخیره در منابع با رمزگذاری یا محاسبه در زمان اجرا. برای Android ProGuard با مبهمسازی ثابتهای رشتهای مؤثر است.
سومین اشتباه — pinning در سطح گواهی توسعه. گواهیهای توسعه و تولید معمولاً متفاوت هستند، اما توسعهدهندگان اغلب فراموش میکنند پینها را هنگام ساخت release تغییر دهند. نتیجه — برنامه تولید نمیتواند به سرور متصل شود. راه حل — پیکربندی جداگانه پینها برای debug و release از طریق BuildConfig یا منابع خاص flavour.
سوالات متداول
SSL Pinning — اصطلاح کلی برای اتصال به گواهی SSL/TLS. Certificate Pinning — پیادهسازی مشخصی که خود گواهی X.509 را تثبیت میکند، نه فقط کلید عمومی. تفاوت در شیء تثبیت: گواهی در مقابل کلید.
توصیه میشود هشها را در منابع با مبهمسازی از طریق ProGuard (Android) یا رمزگذاری شده از طریق Keychain (iOS) ذخیره کنید. از ذخیره پینها به صورت آشکار در strings.xml یا Info.plist بدون رمزگذاری خودداری کنید.
در هر بار تغییر گواهی در سرور. توصیه میشود ۳–۶ ماه قبل از انقضای گواهی فعلی، اثر انگشت جدید را به عنوان پین پشتیبان اضافه کنید و پس از چرخش، قدیمی را حذف کنید. حداقل یک پین پشتیبان الزامی است.
بله، از طریق کامپایل شرطی: در build دیباگ pinning غیرفعال است، در release فعال است. از BuildConfig.DEBUG در Android یا #if DEBUG در iOS برای جابجایی استفاده کنید. هرگز این کار را از طریق پرچم runtime قابل دسترس برای کاربر انجام ندهید.
فوراً بهروزرسانی برنامه را با اثر انگشتهای جدید منتشر کرده و در فروشگاهها منتشر کنید. از مکانیزم بهروزرسانی اجباری استفاده کنید. اگر پینهای پشتیبان شامل اثر انگشت CA پشتیبان بودند، میتوان به طور موقت به دامنه دیگری با گواهی دیگر تغییر مسیر داد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید