APK Signature Scheme v3

اندروید 9 از چرخش کلید APK پشتیبانی می‌کند که به برنامه‌ها این امکان را می‌دهد تا کلید امضای خود را به عنوان بخشی از به‌روزرسانی APK تغییر دهند. برای عملی کردن چرخش، APK باید سطوح اعتماد بین کلید امضای جدید و قدیمی را نشان دهد. برای پشتیبانی از چرخش کلید، طرح امضای APK را از نسخه ۲ به نسخه ۳ به‌روزرسانی کردیم تا بتوانیم از کلیدهای جدید و قدیمی استفاده کنیم. V3 اطلاعاتی در مورد نسخه های SDK پشتیبانی شده و ساختار اثبات چرخش به بلوک امضای APK اضافه می کند.

بلوک امضای APK

برای حفظ سازگاری با فرمت APK v1، امضاهای APK v2 و v3 در داخل یک بلوک امضای APK که بلافاصله قبل از فهرست مرکزی ZIP قرار دارد، ذخیره می‌شوند.

فرمت v3 APK Signing Block مانند v2 است. امضای v3 APK به عنوان یک جفت ID-مقدار با شناسه 0xf05368c0 ذخیره می‌شود.

APK Signature Scheme v3 Block

طرح v3 بسیار شبیه به طرح v2 طراحی شده است. فرمت کلی یکسانی دارد و شناسه‌های الگوریتم امضا ، اندازه‌های کلید و منحنی‌های EC را پشتیبانی می‌کند.

با این حال، طرح v3 اطلاعاتی در مورد نسخه های SDK پشتیبانی شده و ساختار اثبات چرخش اضافه می کند.

فرمت

APK Signature Scheme v3 Block در داخل بلوک امضای APK تحت شناسه 0xf05368c0 .

فرمت APK Signature Scheme v3 Block از فرمت v2 پیروی می کند:

  • دنباله طول پیشوند signer با پیشوند طول:
    • signed data با پیشوند طول:
      • دنباله پیشوند طولی از digests های پیشوند طول:
        • signature algorithm ID (4 بایت)
        • digest (پیشوند طول)
      • توالی پیشوند طول گواهی های certificates :
        • certificate X.509 با پیشوند طول (فرم ASN.1 DER)
      • minSDK (uint32) - اگر نسخه پلتفرم زیر این عدد باشد، این امضاکننده باید نادیده گرفته شود.
      • maxSDK (uint32) - اگر نسخه پلتفرم بالاتر از این عدد باشد، این امضاکننده باید نادیده گرفته شود.
      • دنباله طول-پیشوند از additional attributes طول-پیشوند:
        • ID (uint32)
        • value (طول متغیر: طول ویژگی اضافی - 4 بایت)
        • ID - 0x3ba06f8c
        • value - ساختار اثبات چرخش
    • minSDK (uint32) - تکراری از مقدار minSDK در بخش داده های امضا شده - برای رد شدن از تأیید این امضا در صورتی که پلت فرم فعلی در محدوده نباشد استفاده می شود. باید با مقدار داده امضا شده مطابقت داشته باشد.
    • maxSDK (uint32) - تکراری از مقدار maxSDK در بخش داده های امضا شده - برای رد شدن از تأیید این امضا در صورتی که پلت فرم فعلی در محدوده نباشد استفاده می شود. باید با مقدار داده امضا شده مطابقت داشته باشد.
    • دنباله طول-پیشوند signatures طول-پیشوند:
      • signature algorithm ID (uint32)
      • signature با پیشوند طول روی signed data
    • public key با پیشوند طول (SubjectPublicKeyInfo، فرم ASN.1 DER)

سازه‌های گواهی چرخش اثبات‌شده و قابل اعتماد قدیمی

ساختار اثبات چرخش به برنامه ها اجازه می دهد تا گواهی امضای خود را بدون مسدود شدن در سایر برنامه هایی که با آنها ارتباط برقرار می کنند بچرخانند. برای انجام این کار، امضای برنامه حاوی دو داده جدید است:

  • ادعا برای اشخاص ثالث که گواهی امضای برنامه را می توان در هر کجا که به پیشینیان آن اعتماد کرد، اعتماد کرد.
  • گواهی‌های امضای قدیمی‌تر برنامه که خود برنامه همچنان به آنها اعتماد دارد

ویژگی اثبات چرخش در بخش داده‌های امضا شده از یک فهرست به‌تنهایی تشکیل شده است که هر گره حاوی یک گواهی امضا است که برای امضای نسخه‌های قبلی برنامه استفاده می‌شود. این ویژگی شامل ساختارهای داده اثبات چرخش مفهومی و گواهی‌های قدیمی مورد اعتماد است. لیست بر اساس نسخه با قدیمی ترین گواهی امضای مربوط به گره ریشه مرتب شده است. ساختار داده اثبات چرخش با امضای گواهی در هر گره با علامت بعدی در لیست ساخته می‌شود، و بنابراین هر کلید جدید را با شواهدی مبنی بر اینکه باید به اندازه کلید(های کلیدی) قدیمی‌تر قابل اعتماد باشد، آغشته می‌کند.

ساختار داده گواهی‌های قدیمی با اضافه کردن پرچم‌هایی که عضویت و ویژگی‌های آن را در مجموعه نشان می‌دهد، ساخته می‌شود. به عنوان مثال، ممکن است پرچمی وجود داشته باشد که نشان می دهد گواهی امضا در یک گره معین برای دریافت مجوزهای امضای Android قابل اعتماد است. این پرچم به سایر برنامه‌های امضا شده توسط گواهی قدیمی‌تر اجازه می‌دهد همچنان مجوز امضای تعریف شده توسط برنامه امضا شده با گواهی امضای جدید را داشته باشند. از آنجایی که کل ویژگی اثبات چرخش در بخش داده های امضا شده فیلد signer v3 قرار دارد، توسط کلید مورد استفاده برای امضای apk حاوی محافظت می شود.

این قالب از کلیدهای امضای متعدد و همگرایی گواهی های امضای اجداد مختلف به یک (چند گره شروع به یک سینک مشترک) جلوگیری می کند.

فرمت

اثبات چرخش در داخل APK Signature Scheme v3 Block تحت شناسه 0x3ba06f8c می شود. فرمت آن این است:

  • دنباله طول-پیشوند levels با پیشوند طول:
    • signed data با پیشوند طول (با گواهی قبلی - در صورت وجود)
      • certificate X.509 با پیشوند طول (فرم ASN.1 DER)
      • signature algorithm ID (uint32) - الگوریتم مورد استفاده گواهی در سطح قبلی
    • flags (uint32) - پرچم‌هایی که نشان می‌دهند که آیا این گواهی باید در ساختار گواهی‌های قدیمی-خود اعتماد باشد یا نه، و برای کدام عملیات.
    • signature algorithm ID (uint32) - باید با یکی از بخش داده های امضا شده در سطح بعدی مطابقت داشته باشد.
    • signature با پیشوند طول روی signed data بالا

گواهی های متعدد

Android در حال حاضر یک APK امضا شده با چندین گواهی را به عنوان دارای یک هویت امضای منحصر به فرد جدا از گواهی های متشکل می داند. بنابراین، خصیصه اثبات چرخش در بخش داده‌های امضا شده، یک نمودار غیر چرخه‌ای جهت‌دار را تشکیل می‌دهد، که بهتر می‌توان آن را به‌عنوان یک فهرست تک پیوندی مشاهده کرد، با هر مجموعه امضاکننده برای یک نسخه معین، یک گره را نشان می‌دهد. این پیچیدگی بیشتری به ساختار اثبات چرخش می‌افزاید (نسخه چند امضاکننده در زیر). به طور خاص، سفارش تبدیل به یک نگرانی می شود. علاوه بر این، دیگر امکان امضای فایل‌های APK به‌طور مستقل وجود ندارد، زیرا ساختار اثبات چرخش باید دارای گواهی‌های امضاکننده قدیمی باشد که مجموعه جدید گواهی‌ها را امضا کنند، نه اینکه آنها را یک به یک امضا کنند. به عنوان مثال، یک APK امضا شده توسط کلید A که می‌خواهد با دو کلید جدید B و C امضا شود، نمی‌تواند امضاکننده B را فقط دارای امضای A یا B باشد، زیرا این یک هویت امضا متفاوت از B و C است. به این معنی که امضاکنندگان باید قبل از ایجاد چنین ساختاری هماهنگ شوند.

ویژگی اثبات چرخش چند امضاکننده

  • دنباله طول-پیشوند sets با پیشوند طول:
    • signed data (بر اساس مجموعه قبلی - در صورت وجود)
      • توالی پیشوند طول certificates ها
        • certificate X.509 با پیشوند طول (فرم ASN.1 DER)
      • دنباله signature algorithm IDs (uint32) - یکی برای هر گواهی از مجموعه قبلی، به همان ترتیب.
    • flags (uint32) - پرچم‌هایی که نشان می‌دهند که آیا این مجموعه گواهی‌ها باید در ساختار گواهی‌های قدیمی-خود اعتماد باشند یا نه، و برای کدام عملیات.
    • دنباله طول-پیشوند signatures طول-پیشوند:
      • signature algorithm ID (uint32) - باید با یکی از بخش داده های امضا شده مطابقت داشته باشد
      • signature با پیشوند طول روی signed data بالا

اجداد متعدد در ساختار اثبات چرخش

طرح v3 همچنین نمی‌تواند دو کلید مختلف را به سمت کلید امضای یکسان برای یک برنامه بچرخاند. این با مورد خرید متفاوت است، جایی که شرکت خریدار می‌خواهد برنامه خریداری‌شده را به استفاده از کلید امضای آن برای اشتراک‌گذاری مجوزها منتقل کند. این اکتساب به عنوان یک مورد استفاده پشتیبانی شده در نظر گرفته می شود زیرا برنامه جدید با نام بسته خود متمایز می شود و می تواند ساختار اثبات چرخش خود را داشته باشد. مورد پشتیبانی نشده، از یک برنامه که دو مسیر متفاوت برای رسیدن به گواهی یکسان دارد، بسیاری از فرضیات ساخته شده در طراحی چرخش کلید را زیر پا می گذارد.

تایید

در اندروید 9 و بالاتر، فایل‌های APK را می‌توان بر اساس طرح امضای APK نسخه 3، نسخه 2، یا طرح v1 تأیید کرد. پلتفرم‌های قدیمی‌تر امضاهای v3 را نادیده می‌گیرند و سعی می‌کنند امضاهای v2 و سپس v1 را تأیید کنند.

فرآیند تأیید امضای APK

شکل 1. فرآیند تأیید امضای APK

تأیید APK Signature Scheme v3

  1. بلوک امضای APK را پیدا کنید و تأیید کنید که:
    1. دو فیلد اندازه بلوک امضای APK حاوی یک مقدار است.
    2. ZIP Central Directory بلافاصله پس از ZIP End of Central Directory ثبت می شود.
    3. پایان ZIP از دایرکتوری مرکزی با داده های بیشتری دنبال نمی شود.
  2. اولین بلوک APK Signature Scheme v3 را در داخل بلوک امضای APK قرار دهید. اگر بلوک v3 وجود دارد، به مرحله 3 بروید. در غیر این صورت، به تأیید APK با استفاده از طرح v2 برگردید.
  3. برای هر signer در APK Signature Scheme v3 Block با حداقل و حداکثر نسخه SDK که در محدوده پلتفرم فعلی قرار دارد:
    1. قوی ترین signature algorithm ID پشتیبانی شده را از signatures انتخاب کنید. ترتیب قدرت به هر نسخه پیاده سازی/پلتفرم بستگی دارد.
    2. signature مربوطه را از signatures در برابر signed data با استفاده از public key تأیید کنید. (اکنون تجزیه signed data ایمن است.)
    3. بررسی کنید که نسخه‌های حداقل و حداکثر SDK در داده‌های امضا شده با آنچه برای signer مشخص شده است مطابقت داشته باشند.
    4. بررسی کنید که لیست مرتب شده شناسه های الگوریتم امضا در digests ها و signatures یکسان است. (این برای جلوگیری از حذف/افزودن امضا است.)
    5. خلاصه محتویات APK را با استفاده از الگوریتم خلاصه مشابه الگوریتم خلاصه مورد استفاده توسط الگوریتم امضا محاسبه کنید.
    6. بررسی کنید که خلاصه محاسبه شده با digest مربوطه از digests ها یکسان است.
    7. بررسی کنید که SubjectPublicKeyInfo اولین certificate با public key یکسان certificates .
    8. اگر ویژگی اثبات چرخش برای signer وجود دارد، بررسی کنید که ساختار معتبر است و این signer آخرین گواهی در لیست است.
  4. اگر دقیقاً یک signer در محدوده پلتفرم فعلی پیدا شود و مرحله 3 برای آن signer موفقیت آمیز باشد، تأیید موفقیت آمیز است.

اعتبار سنجی

برای آزمایش اینکه آیا دستگاه شما نسخه 3 را به درستی پشتیبانی می‌کند، PkgInstallSignatureVerificationTest.java CTS را در cts/hostsidetests/appsecurity/src/android/appsecurity/cts/ اجرا کنید.