تابلوهای ساخت برای انتشار

تصاویر سیستم عامل اندروید در دو مکان از امضای رمزنگاری استفاده می کنند:

  1. هر فایل .apk داخل تصویر باید امضا شود. Package Manager Android به دو صورت از امضای .apk استفاده می کند:
    • هنگامی که یک برنامه جایگزین می شود، باید با همان کلید برنامه قدیمی امضا شود تا بتوان به داده های برنامه قدیمی دسترسی داشت. این امر هم برای به‌روزرسانی برنامه‌های کاربر با رونویسی .apk و هم برای لغو برنامه سیستمی با نسخه جدیدتر نصب شده در /data صادق است.
    • اگر دو یا چند برنامه بخواهند شناسه کاربری را به اشتراک بگذارند (تا بتوانند داده ها و غیره را به اشتراک بگذارند)، باید با همان کلید امضا شوند.
  2. بسته های به روز رسانی OTA باید با یکی از کلیدهای مورد انتظار سیستم امضا شوند، در غیر این صورت فرآیند نصب آنها را رد می کند.

کلیدهای آزادسازی

درخت اندروید شامل کلیدهای آزمایشی زیر build/target/product/security است. ساختن یک تصویر سیستم عامل Android با استفاده از make ، همه فایل‌های .apk را با استفاده از کلیدهای تست امضا می‌کند. از آنجایی که کلیدهای آزمایشی به طور عمومی شناخته شده اند، هر کسی می تواند فایل های apk. خود را با کلیدهای یکسان امضا کند، که ممکن است به آنها اجازه دهد برنامه های سیستمی ساخته شده در تصویر سیستم عامل شما را جایگزین یا ربوده کنند. به همین دلیل بسیار مهم است که هر تصویر عمومی منتشر شده یا مستقر در سیستم عامل اندروید را با مجموعه خاصی از کلیدهای انتشار امضا کنید که فقط شما به آنها دسترسی دارید.

برای ایجاد مجموعه منحصر به فرد خود از کلیدهای انتشار، این دستورات را از ریشه درخت اندروید خود اجرا کنید:

subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'
mkdir ~/.android-certs
for x in releasekey platform shared media networkstack; do \
    ./development/tools/make_key ~/.android-certs/$x "$subject"; \
  done

$subject باید تغییر کند تا اطلاعات سازمان شما را منعکس کند. می توانید از هر دایرکتوری استفاده کنید، اما مراقب باشید مکانی را انتخاب کنید که پشتیبان گیری شده و ایمن باشد. برخی از فروشندگان انتخاب می کنند که کلید خصوصی خود را با یک عبارت عبور قوی رمزگذاری کنند و کلید رمزگذاری شده را در کنترل منبع ذخیره کنند. برخی دیگر کلیدهای آزادسازی خود را به طور کامل در جای دیگری ذخیره می‌کنند، مثلاً در یک رایانه با شکاف هوا.

برای ایجاد یک تصویر انتشار، از:

make dist
sign_target_files_apks \
-o \    # explained in the next section
--default_key_mappings ~/.android-certs out/dist/*-target_files-*.zip \
signed-target_files.zip

اسکریپت sign_target_files_apks یک target-files .zip به عنوان ورودی می گیرد و یک target-files .zip جدید تولید می کند که در آن همه فایل های .apk با کلیدهای جدید امضا شده اند. تصاویری که به تازگی امضا کرده اند را می توان در زیر IMAGES/ در signed-target_files.zip پیدا کرد.

بسته های OTA را امضا کنید

یک فایل فشرده هدف امضا شده را می توان با استفاده از روش زیر به یک فایل فشرده به روز رسانی OTA امضا شده تبدیل کرد:
ota_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

امضا و بارگذاری جانبی

بارگذاری جانبی مکانیسم تأیید امضای بسته بازیابی معمولی را دور نمی زند - قبل از نصب بسته، بازیابی تأیید می کند که با یکی از کلیدهای خصوصی مطابق با کلیدهای عمومی ذخیره شده در پارتیشن بازیابی امضا شده است، دقیقاً همانطور که برای بسته ای که از طریق بسته تحویل داده می شود. -هوا

بسته‌های به‌روزرسانی دریافت‌شده از سیستم اصلی معمولاً دو بار تأیید می‌شوند: یک بار توسط سیستم اصلی، با استفاده از روش RecoverySystem.verifyPackage() در API اندروید، و سپس دوباره با بازیابی. RecoverySystem API امضا را در برابر کلیدهای عمومی ذخیره شده در سیستم اصلی، در فایل /system/etc/security/otacerts.zip (به طور پیش فرض) بررسی می کند. Recovery امضای کلیدهای عمومی ذخیره شده در دیسک RAM پارتیشن بازیابی را در فایل /res/keys بررسی می کند.

به طور پیش‌فرض، فایل‌های .zip تولید شده توسط بیلد، گواهی OTA را مطابق با کلید تست تنظیم می‌کند. در تصویر منتشر شده، باید از گواهی متفاوتی استفاده شود تا دستگاه‌ها بتوانند صحت بسته به‌روزرسانی را تأیید کنند. ارسال پرچم -o به sign_target_files_apks ، همانطور که در بخش قبل نشان داده شده است، گواهی کلید تست را با گواهی کلید انتشار از دایرکتوری certs جایگزین می کند.

معمولاً تصویر سیستم و تصویر بازیابی مجموعه ای از کلیدهای عمومی OTA را ذخیره می کنند. با افزودن یک کلید فقط به مجموعه کلیدهای بازیابی، می توان بسته هایی را امضا کرد که فقط از طریق بارگذاری جانبی قابل نصب هستند (با فرض اینکه مکانیسم دانلود به روز رسانی سیستم اصلی به درستی تأیید را در برابر otacerts.zip انجام می دهد). با تنظیم متغیر PRODUCT_EXTRA_RECOVERY_KEYS در تعریف محصول خود، می‌توانید کلیدهای اضافی را مشخص کنید تا فقط در بازیابی گنجانده شوند:

vendor/yoyodyne/tardis/products/tardis.mk
 [...]

PRODUCT_EXTRA_RECOVERY_KEYS := vendor/yoyodyne/security/tardis/sideload

این شامل کلید عمومی vendor/yoyodyne/security/tardis/sideload.x509.pem در فایل کلیدهای بازیابی است تا بتواند بسته های امضا شده با آن را نصب کند. با این حال، کلید اضافی در otacerts.zip گنجانده نشده است، بنابراین سیستم‌هایی که بسته‌های دانلود شده را به درستی تأیید می‌کنند، بازیابی بسته‌های امضا شده با این کلید را احضار نمی‌کنند.

گواهینامه ها و کلیدهای خصوصی

هر کلید در دو فایل ارائه می شود: گواهی با پسوند .x509.pem و کلید خصوصی با پسوند pk8. کلید خصوصی باید مخفی بماند و برای امضای بسته مورد نیاز است. ممکن است خود کلید با رمز عبور محافظت شود. در مقابل، گواهی تنها حاوی نیمی از کلید عمومی است، بنابراین می توان آن را به طور گسترده توزیع کرد. برای تأیید اینکه یک بسته توسط کلید خصوصی مربوطه امضا شده است استفاده می شود.

ساخت استاندارد اندروید از پنج کلید استفاده می کند که همه آنها در build/target/product/security قرار دارند:

کلید تست
کلید پیش فرض عمومی برای بسته هایی که در غیر این صورت کلیدی را مشخص نمی کنند.
سکو
کلید تست برای بسته هایی که بخشی از پلت فرم اصلی هستند.
به اشتراک گذاشته شده است
کلید تست برای چیزهایی که در فرآیند خانه/مخاطبین به اشتراک گذاشته شده است.
رسانه ها
کلید تست برای بسته هایی که بخشی از سیستم رسانه/دانلود هستند.
پشته شبکه
کلید تست برای بسته هایی که بخشی از سیستم شبکه هستند. کلید شبکه پشته برای امضای باینری های طراحی شده به عنوان اجزای سیستم مدولار استفاده می شود. اگر به‌روزرسانی‌های ماژول شما به‌طور جداگانه ساخته شده‌اند و به‌عنوان پیش‌ساخته‌شده در تصویر دستگاه شما یکپارچه شده‌اند، ممکن است نیازی به ایجاد یک کلید شبکه پشته در درخت منبع Android نداشته باشید.

بسته های فردی با تنظیم LOCAL_CERTIFICATE در فایل Android.mk خود یکی از این کلیدها را مشخص می کنند. (اگر این متغیر تنظیم نشده باشد از کلید تست استفاده می شود.) همچنین می توانید یک کلید کاملاً متفاوت را با نام مسیر مشخص کنید، به عنوان مثال:

device/yoyodyne/apps/SpecialApp/Android.mk
 [...]

LOCAL_CERTIFICATE := device/yoyodyne/security/special

اکنون ساختنی از کلید device/yoyodyne/security/special.{x509.pem,pk8} برای امضای SpecialApp.apk استفاده می‌کند. این بیلد فقط می تواند از کلیدهای خصوصی استفاده کند که با رمز عبور محافظت نمی شوند.

گزینه های پیشرفته امضا

جایگزینی کلید امضای APK

اسکریپت امضا sign_target_files_apks روی فایل های هدف تولید شده برای ساخت کار می کند. تمام اطلاعات مربوط به گواهی ها و کلیدهای خصوصی مورد استفاده در زمان ساخت در فایل های هدف گنجانده شده است. هنگام اجرای اسکریپت امضا برای امضا برای انتشار، کلیدهای امضا را می توان بر اساس نام کلید یا نام APK جایگزین کرد.

از پرچم های --key_mapping و --default_key_mappings برای تعیین جایگزینی کلید بر اساس نام کلیدها استفاده کنید:

  • پرچم --key_mapping src_key = dest_key جایگزینی برای یک کلید در هر زمان را مشخص می کند.
  • پرچم --default_key_mappings dir یک دایرکتوری با پنج کلید برای جایگزینی همه کلیدها در build/target/product/security مشخص می کند. معادل پنج بار استفاده از --key_mapping برای تعیین نگاشتها است.
build/target/product/security/testkey      = dir/releasekey
build/target/product/security/platform     = dir/platform
build/target/product/security/shared       = dir/shared
build/target/product/security/media        = dir/media
build/target/product/security/networkstack = dir/networkstack

از --extra_apks apk_name1,apk_name2,... = key برای تعیین جایگزینی کلید امضا بر اساس نام های APK استفاده کنید. اگر key خالی بماند، اسکریپت با APK های مشخص شده به عنوان از پیش امضا شده رفتار می کند.

برای محصول فرضی tardis، به شش کلید محافظت شده با رمز عبور نیاز دارید: پنج کلید برای جایگزینی پنج کلید در build/target/product/security ، و یکی برای جایگزینی کلید اضافی device/yoyodyne/security/special مورد نیاز SpecialApp در مثال بالا. اگر کلیدها در فایل های زیر بودند:

vendor/yoyodyne/security/tardis/releasekey.x509.pem
vendor/yoyodyne/security/tardis/releasekey.pk8
vendor/yoyodyne/security/tardis/platform.x509.pem
vendor/yoyodyne/security/tardis/platform.pk8
vendor/yoyodyne/security/tardis/shared.x509.pem
vendor/yoyodyne/security/tardis/shared.pk8
vendor/yoyodyne/security/tardis/media.x509.pem
vendor/yoyodyne/security/tardis/media.pk8
vendor/yoyodyne/security/tardis/networkstack.x509.pem
vendor/yoyodyne/security/tardis/networkstack.pk8
vendor/yoyodyne/security/special.x509.pem
vendor/yoyodyne/security/special.pk8           # NOT password protected
vendor/yoyodyne/security/special-release.x509.pem
vendor/yoyodyne/security/special-release.pk8   # password protected

سپس همه برنامه ها را به این صورت امضا می کنید:

./build/make/tools/releasetools/sign_target_files_apks \
    --default_key_mappings vendor/yoyodyne/security/tardis \
    --key_mapping vendor/yoyodyne/security/special=vendor/yoyodyne/security/special-release \
    --extra_apks PresignedApp= \
    -o tardis-target_files.zip \
    signed-tardis-target_files.zip

این موارد زیر را به همراه دارد:

Enter password for vendor/yoyodyne/security/special-release key>
Enter password for vendor/yoyodyne/security/tardis/networkstack key>
Enter password for vendor/yoyodyne/security/tardis/media key>
Enter password for vendor/yoyodyne/security/tardis/platform key>
Enter password for vendor/yoyodyne/security/tardis/releasekey key>
Enter password for vendor/yoyodyne/security/tardis/shared key>
    signing: Phone.apk (vendor/yoyodyne/security/tardis/platform)
    signing: Camera.apk (vendor/yoyodyne/security/tardis/media)
    signing: NetworkStack.apk (vendor/yoyodyne/security/tardis/networkstack)
    signing: Special.apk (vendor/yoyodyne/security/special-release)
    signing: Email.apk (vendor/yoyodyne/security/tardis/releasekey)
        [...]
    signing: ContactsProvider.apk (vendor/yoyodyne/security/tardis/shared)
    signing: Launcher.apk (vendor/yoyodyne/security/tardis/shared)
NOT signing: PresignedApp.apk
        (skipped due to special cert string)
rewriting SYSTEM/build.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
     with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
    signing: framework-res.apk (vendor/yoyodyne/security/tardis/platform)
rewriting RECOVERY/RAMDISK/default.prop:
  replace:  ro.build.description=tardis-user Eclair ERC91 15449 test-keys
     with:  ro.build.description=tardis-user Eclair ERC91 15449 release-keys
  replace: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/test-keys
     with: ro.build.fingerprint=generic/tardis/tardis/tardis:Eclair/ERC91/15449:user/release-keys
using:
    vendor/yoyodyne/security/tardis/releasekey.x509.pem
for OTA package verification
done.

پس از درخواست از کاربر برای رمزهای عبور برای همه کلیدهای محافظت شده با رمز عبور، اسکریپت دوباره همه فایل‌های APK موجود در .zip را با کلیدهای انتشار دوباره امضا می‌کند. قبل از اجرای دستور، می‌توانید متغیر محیطی ANDROID_PW_FILE را نیز روی نام فایل موقت تنظیم کنید. سپس اسکریپت ویرایشگر شما را فراخوانی می کند تا به شما اجازه دهد رمز عبور همه کلیدها را وارد کنید (این ممکن است راه راحت تری برای وارد کردن رمز عبور باشد).

جایگزینی کلید امضای APEX

اندروید 10 فرمت فایل APEX را برای نصب ماژول های سطح پایین سیستم معرفی می کند. همانطور که در امضای APEX توضیح داده شد، هر فایل APEX با دو کلید امضا می شود: یکی برای تصویر سیستم فایل کوچک در یک APEX و دیگری برای کل APEX.

هنگام امضای برای انتشار، دو کلید امضا برای یک فایل APEX با کلیدهای انتشار جایگزین می شوند. کلید payload سیستم فایل با پرچم --extra_apex_payload و کل کلید امضای فایل APEX با پرچم --extra_apks مشخص شده است.

برای محصول tardis، فرض کنید که پیکربندی کلید زیر را برای فایل‌های com.android.conscrypt.apex ، com.android.media.apex ، و com.android.runtime.release.apex APEX دارید.

name="com.android.conscrypt.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED"
name="com.android.media.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED"
name="com.android.runtime.release.apex" public_key="vendor/yoyodyne/security/testkeys/com.android.runtime.avbpubkey" private_key="vendor/yoyodyne/security/testkeys/com.android.runtime.pem" container_certificate="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.x509.pem" container_private_key="vendor/yoyodyne/security/testkeys/com.google.android.runtime.release_container.pk8"

و فایل های زیر را دارید که حاوی کلیدهای انتشار هستند:

vendor/yoyodyne/security/runtime_apex_container.x509.pem
vendor/yoyodyne/security/runtime_apex_container.pk8
vendor/yoyodyne/security/runtime_apex_payload.pem

فرمان زیر کلیدهای امضای com.android.runtime.release.apex و com.android.tzdata.apex را در هنگام امضای انتشار لغو می کند. به طور خاص، com.android.runtime.release.apex با کلیدهای انتشار مشخص شده امضا می شود ( runtime_apex_container برای فایل APEX، و runtime_apex_payload برای بار تصویر فایل). com.android.tzdata.apex به عنوان از پیش امضا شده تلقی می شود. همه فایل‌های APEX دیگر با پیکربندی پیش‌فرض همانطور که در فایل‌های هدف فهرست شده است، مدیریت می‌شوند.

./build/make/tools/releasetools/sign_target_files_apks \
    --default_key_mappings   vendor/yoyodyne/security/tardis \
    --extra_apks             com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_container \
    --extra_apex_payload_key com.android.runtime.release.apex=vendor/yoyodyne/security/runtime_apex_payload.pem \
    --extra_apks             com.android.media.apex= \
    --extra_apex_payload_key com.android.media.apex= \
    -o tardis-target_files.zip \
    signed-tardis-target_files.zip

با اجرای دستور بالا، لاگ های زیر به دست می آید:

        [...]
    signing: com.android.runtime.release.apex                  container (vendor/yoyodyne/security/runtime_apex_container)
           : com.android.runtime.release.apex                  payload   (vendor/yoyodyne/security/runtime_apex_payload.pem)
NOT signing: com.android.conscrypt.apex
        (skipped due to special cert string)
NOT signing: com.android.media.apex
        (skipped due to special cert string)
        [...]

گزینه های دیگر

اسکریپت امضا sign_target_files_apks توضیحات ساخت و اثر انگشت را در فایل‌های Build Properties بازنویسی می‌کند تا نشان دهد که بیلد یک ساخت امضا شده است. پرچم --tag_changes کنترل می کند که چه ویرایش هایی روی اثر انگشت انجام می شود. اسکریپت را با -h اجرا کنید تا مستندات روی همه پرچم ها را ببینید.

کلیدها را به صورت دستی تولید کنید

Android از کلیدهای RSA 2048 بیتی با توان 3 عمومی استفاده می‌کند. می‌توانید جفت‌های گواهی/کلید خصوصی را با استفاده از ابزار openssl از openssl.org ایجاد کنید:

# generate RSA key
openssl genrsa -3 -out temp.pem 2048
Generating RSA private key, 2048 bit long modulus
....+++
.....................+++
e is 3 (0x3)

# create a certificate with the public part of the key
openssl req -new -x509 -key temp.pem -out releasekey.x509.pem -days 10000 -subj '/C=US/ST=California/L=San Narciso/O=Yoyodyne, Inc./OU=Yoyodyne Mobility/CN=Yoyodyne/emailAddress=yoyodyne@example.com'

# create a PKCS#8-formatted version of the private key
openssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt

# securely delete the temp.pem file
shred --remove temp.pem

دستور openssl pkcs8 داده شده در بالا یک فایل pk8. بدون رمز عبور ایجاد می کند که برای استفاده در سیستم ساخت مناسب است. برای ایجاد یک .pk8 ایمن شده با رمز عبور (که باید برای همه کلیدهای انتشار واقعی انجام دهید)، آرگومان -nocrypt با -passout stdin جایگزین کنید. سپس openssl کلید خصوصی را با رمز عبور خوانده شده از ورودی استاندارد رمزگذاری می کند. هیچ درخواستی چاپ نمی‌شود، بنابراین اگر stdin ترمینال باشد، برنامه زمانی که واقعاً منتظر است رمز عبور را وارد کنید، به نظر می‌رسد که هنگ می‌کند. مقادیر دیگر را می توان برای آرگومان the-passout برای خواندن رمز عبور از مکان های دیگر استفاده کرد. برای جزئیات، به مستندات openssl مراجعه کنید.

فایل میانی temp.pem حاوی کلید خصوصی بدون هیچ گونه حفاظت رمز عبور است، بنابراین هنگام ایجاد کلیدهای انتشار، آن را با دقت دور بریزید. به طور خاص، ابزار GNUshred ممکن است بر روی سیستم های فایل شبکه یا ژورنال موثر نباشد. هنگام تولید کلیدها می توانید از یک دایرکتوری کار واقع در یک دیسک RAM (مانند یک پارتیشن tmpfs) استفاده کنید تا اطمینان حاصل کنید که واسطه ها به طور ناخواسته در معرض نمایش قرار نمی گیرند.

فایل های تصویری ایجاد کنید

هنگامی که signed-target_files.zip را دارید، باید تصویر را ایجاد کنید تا بتوانید آن را در یک دستگاه قرار دهید. برای ایجاد تصویر امضا شده از فایل های هدف، دستور زیر را از ریشه درخت اندروید اجرا کنید:

img_from_target_files signed-target_files.zip signed-img.zip
فایل به دست آمده، signed-img.zip ، حاوی تمام فایل های .img است. برای بارگذاری یک تصویر روی دستگاه، از fastboot به صورت زیر استفاده کنید:
fastboot update signed-img.zip