Certificate Pinning: چیست، مکانیزم و روش‌های تثبیت

نویسنده: IT Sectr منتشر شده: 2026-03-09 زمان مطالعه: 8 دقیقه

Certificate Pinning — مکانیزم تثبیت گواهی یا کلید عمومی سرور، که در آن برنامه از اثر انگشت از پیش شناخته شده برای بررسی اتصال HTTPS استفاده می‌کند. برخلاف زنجیره اعتماد استاندارد از طریق CA، pinning تضمین می‌کند که حتی یک مرکز صدور گواهی به خطر افتاده نمی‌تواند گواهی جعلی برای دامنه شما صادر کند. طبق OWASP MSTG (2025)، Certificate Pinning در فهرست کنترل‌های اجباری برای برنامه‌های با سطح حفاظت L2 قرار دارد. پیاده‌سازی شامل ذخیره هش‌های گواهی در کد و بررسی در هر درخواست است.

نکات اصلی

  • Certificate Pinning — تکنیکی که در آن برنامه فقط به گواهی با اثر انگشت از پیش شناخته شده اعتماد می‌کند و کل زنجیره CA را نادیده می‌گیرد
  • Public Key Pinning — جایگزینی که فقط کلید عمومی را تثبیت می‌کند و چرخش را در تغییر گواهی ساده‌تر می‌کند
  • HPKP (HTTP Public Key Pinning) — استاندارد قدیمی در سطح هدرهای HTTP، برای پروژه‌های جدید توصیه نمی‌شود
  • Backup pins — اثر انگشت‌های پشتیبان که تداوم اتصال را هنگام تغییر یا انقضای گواهی اصلی تضمین می‌کنند
  • پیاده‌سازی در iOS از طریق SecTrustEvaluate، در Android از طریق CertificatePinner در OkHttp یا TrustManager

Certificate Pinning چیست؟

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

در ابتدا Certificate Pinning در مرورگرها از طریق مکانیزم HPKP (HTTP Public Key Pinning) استفاده می‌شد که در RFC 7469 استاندارد شده بود. توسعه‌دهنده هدر HTTP Public-Key-Pins را با هش‌های کلیدهای مورد انتظار ارسال می‌کرد و مرورگر آنها را برای مدت مشخصی ذخیره می‌کرد. با این حال HPKP خطرناک بود: یک اشتباه در پیکربندی می‌توانست سایت را برای ماه‌ها مسدود کند. در سال ۲۰۱۸ کروم پشتیبانی از HPKP را متوقف کرد و اکنون استاندارد پیاده‌سازی نرم‌افزاری در سمت کلاینت — داخل برنامه موبایل یا افزونه مرورگر است.

Certificate Pinning چگونه کار می‌کند؟

فرآیند Certificate Pinning شامل سه مرحله کلیدی است: محاسبه اثر انگشت، بررسی در اتصال و مدیریت خطا. در مرحله آماده‌سازی، توسعه‌دهنده هش SHA-256 گواهی یا کلید عمومی سرور تولید را دریافت می‌کند. برای برنامه‌های سازگار با GDPR و PCI DSS همچنین تثبیت اثر انگشت‌های CA میانی در زنجیره الزامی است.

در هر درخواست HTTPS، برنامه callback احراز هویت TLS را رهگیری می‌کند، گواهی سرور را استخراج می‌کند و هش SHA-256 آن را محاسبه می‌کند. این هش با فهرست ذخیره شده اثر انگشت‌های مورد اعتماد مقایسه می‌شود. اگر تطبیق یافت شود — اتصال ادامه می‌یابد. اگر نه — برنامه باید اتصال را قطع کند و خطا را گزارش دهد، بدون اینکه جزئیات پیاده‌سازی را برای مهاجم فاش کند.

kotlin
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 کدگذاری می‌شود. نتیجه با اثر انگشت مورد انتظار مقایسه می‌شود. در محیط تولید، افزودن بررسی روی آرایه‌ای از ۲–۳ اثر انگشت برای پشتیبانی از چرخش مفید است.

Certificate Pinning در مقابل Public Key Pinning

در پیاده‌سازی pinning باید انتخاب کرد که کدام شیء رمزنگاری تثبیت شود. Certificate Pinning به خود گواهی X.509 — شماره سریال، مدت اعتبار و کل زنجیره آن متصل می‌شود. Public Key Pinning فقط کلید عمومی داخل گواهی را تثبیت می‌کند و سایر فیلدها را نادیده می‌گیرد. انتخاب تأثیر قابل توجهی بر هزینه‌های عملیاتی دارد.

معیارCertificate PinningPublic Key Pinning
شیء تثبیتکل گواهی X.509کلید عمومی RSA/ECDSA
چرخشنیاز به به‌روزرسانی در هر بار صدور مجدد داردبا تغییر گواهی با همان کلید تغییر نمی‌کند
امنیتاتصال حداکثر دقیقکمتر به جزئیات حساس است
انعطاف‌پذیریکم — گواهی‌ها هر ۱–۲ سال تغییر می‌کنندبالا — کلیدها می‌توانند ۵–۱۰ سال عمر کنند
توصیهبرای سیستم‌های حیاتی با به‌روزرسانی‌های کنترل شدهبرای بیشتر برنامه‌های موبایل و API

Public Key Pinning — انتخاب ترجیحی برای بیشتر پروژه‌ها. کلیدهای عمومی سرورها معمولاً در هنگام صدور مجدد گواهی بدون تغییر می‌مانند — شرکت به سادگی کلید قدیمی را با گواهی جدید امضا می‌کند. این بدان معناست که اگر جفت کلید تغییر نکرده باشد، برنامه پس از تغییر گواهی نیازی به به‌روزرسانی ندارد. Certificate Pinning برای سناریوهایی توصیه می‌شود که توسعه‌دهنده هم سرور و هم کد کلاینت را کاملاً کنترل می‌کند، مثلاً در برنامه‌های سازمانی با چرخه به‌روزرسانی سخت.

Trust On First Use (TOFU)

TOFU — استراتژی که در آن Certificate Pinning از قبل پیکربندی نمی‌شود، بلکه گواهی را در اولین اتصال به سرور ذخیره می‌کند. این رویکرد برای برنامه‌هایی مناسب است که از قبل نمی‌دانند به کدام سرور متصل خواهند شد. نقطه ضعف — آسیب‌پذیری در حمله اول: اگر اولین اتصال رهگیری شود، گواهی جعلی به عنوان معتبر پذیرفته می‌شود. TOFU در اتصالات SSH و برخی پروتکل‌های P2P استفاده می‌شود.

پیاده‌سازی در iOS و Android

در هر دو پلتفرم، Certificate Pinning از طریق رهگیری اتصال TLS در سطح پشته شبکه پیاده‌سازی می‌شود. در iOS از delegate URLSession یا Alamofire ServerTrustManager استفاده می‌شود. در Android روش ترجیحی OkHttp CertificatePinner است که در کلاینت‌های HTTP محبوب تعبیه شده و از پیکربندی چندین اثر انگشت برای هر دامنه پشتیبانی می‌کند.

swift
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 فراهم می‌کند.

TrustManager برای Android (سفارشی)

اگر برنامه از OkHttp استفاده نمی‌کند، Certificate Pinning را می‌توان از طریق X509TrustManager سفارشی پیاده‌سازی کرد. این روش به کد بیشتری نیاز دارد، اما کنترل کامل بر فرآیند اعتبارسنجی می‌دهد. TrustManager متد checkServerTrusted را بازنویسی می‌کند، جایی که توسعه‌دهنده دستی گواهی‌های سرور را بررسی و درباره اعتماد تصمیم می‌گیرد. فقط برای سناریوهای خاص که کتابخانه OkHttp در دسترس نیست توصیه می‌شود.

اشتباهات در پیاده‌سازی Certificate Pinning

رایج‌ترین اشتباه — فقدان پین‌های پشتیبان. توسعه‌دهنده یک اثر انگشت گواهی را قرار می‌دهد و پس از انقضای آن کاربران به طور گسترده اتصال را از دست می‌دهند. حداقل پیکربندی قابل قبول — دو اثر انگشت: گواهی فعلی و پشتیبان. بهینه — سه: فعلی، پشتیبان و اثر انگشت CA ریشه به عنوان fallback.

دومین اشتباه — ذخیره پین‌ها به صورت آشکار در کد. مهاجم با دسترسی به APK یا IPA می‌تواند به راحتی اثر انگشت‌ها را استخراج و جایگزین کند. توصیه می‌شود هش‌ها مبهم‌سازی شوند: تقسیم رشته به بخش‌ها، ذخیره در منابع با رمزگذاری یا محاسبه در زمان اجرا. برای Android ProGuard با مبهم‌سازی ثابت‌های رشته‌ای مؤثر است.

سومین اشتباه — pinning در سطح گواهی توسعه. گواهی‌های توسعه و تولید معمولاً متفاوت هستند، اما توسعه‌دهندگان اغلب فراموش می‌کنند پین‌ها را هنگام ساخت release تغییر دهند. نتیجه — برنامه تولید نمی‌تواند به سرور متصل شود. راه حل — پیکربندی جداگانه پین‌ها برای debug و release از طریق BuildConfig یا منابع خاص flavour.

  • Ignoring certificate chain — بررسی فقط گواهی leaf بدون در نظر گرفتن CAهای میانی که اتصال را در چرخش می‌شکند
  • Hardcoded dates — تاریخ‌های انقضای گواهی به صورت سخت‌کد شده که پس از به‌روزرسانی تغییر نمی‌کنند
  • No monitoring — عدم هشدار برای خطاهای Certificate Pinning که باعث می‌شود مشکلات فقط از کاربران کشف شوند
  • TOFU بدون اعتبارسنجی — استفاده از Trust On First Use بدون بررسی اضافی که به اولین حمله MITM اجازه می‌دهد گواهی جعلی را تثبیت کند

سوالات متداول

Certificate Pinning چه تفاوتی با SSL Pinning دارد؟

SSL Pinning — اصطلاح کلی برای اتصال به گواهی SSL/TLS. Certificate Pinning — پیاده‌سازی مشخصی که خود گواهی X.509 را تثبیت می‌کند، نه فقط کلید عمومی. تفاوت در شیء تثبیت: گواهی در مقابل کلید.

چگونه اثر انگشت گواهی‌ها را به صورت امن در برنامه ذخیره کنیم؟

توصیه می‌شود هش‌ها را در منابع با مبهم‌سازی از طریق ProGuard (Android) یا رمزگذاری شده از طریق Keychain (iOS) ذخیره کنید. از ذخیره پین‌ها به صورت آشکار در strings.xml یا Info.plist بدون رمزگذاری خودداری کنید.

هر چند وقت یک بار باید اثر انگشت‌های pinned را تغییر داد؟

در هر بار تغییر گواهی در سرور. توصیه می‌شود ۳–۶ ماه قبل از انقضای گواهی فعلی، اثر انگشت جدید را به عنوان پین پشتیبان اضافه کنید و پس از چرخش، قدیمی را حذف کنید. حداقل یک پین پشتیبان الزامی است.

آیا می‌توان Certificate Pinning را برای اشکال‌زدایی غیرفعال کرد؟

بله، از طریق کامپایل شرطی: در build دیباگ pinning غیرفعال است، در release فعال است. از BuildConfig.DEBUG در Android یا #if DEBUG در iOS برای جابجایی استفاده کنید. هرگز این کار را از طریق پرچم runtime قابل دسترس برای کاربر انجام ندهید.

اگر گواهی به خطر افتاده باشد چه باید کرد؟

فوراً به‌روزرسانی برنامه را با اثر انگشت‌های جدید منتشر کرده و در فروشگاه‌ها منتشر کنید. از مکانیزم به‌روزرسانی اجباری استفاده کنید. اگر پین‌های پشتیبان شامل اثر انگشت CA پشتیبان بودند، می‌توان به طور موقت به دامنه دیگری با گواهی دیگر تغییر مسیر داد.

خلاصه

  • Certificate Pinning — تثبیت گواهی مورد اعتماد یا کلید عمومی آن برای محافظت در برابر حملات MITM از طریق CAهای جعلی
  • دو رویکرد — certificate pinning (سخت، به گواهی) و public key pinning (انعطاف‌پذیر، به کلید عمومی)
  • پین‌های پشتیبان الزامی — حداقل ۲ اثر انگشت برای تضمین تداوم در چرخش گواهی‌ها
  • OkHttp CertificatePinner — روش استاندارد پیاده‌سازی در Android با پشتیبانی از چندین پین
  • URLSessionDelegate — روش اصلی در iOS با بررسی دستی SecTrust و هش‌های SHA-256
  • اشتباهات — فقدان پین‌های پشتیبان، ذخیره بدون مبهم‌سازی، اشتباه در پیکربندی debug/release
  • توصیه — استفاده از public key pinning برای بیشتر پروژه‌ها و Certificate Pinning فقط برای سیستم‌های حیاتی

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید