تصاویر سیستمعامل Android از امضاهای رمزنگاری در دو مکان استفاده میکنند:
- هر فایل
.apkدرون تصویر باید امضا شده باشد. «مدیر بسته» Android به دو روش از امضای.apkاستفاده میکند:- وقتی برنامهای جایگزین میشود، باید با همان کلید برنامه قدیمی امضا شود تا بتواند به دادههای برنامه قدیمی دسترسی پیدا کند. این موضوع هم برای بهروزرسانی برنامههای کاربر با بازنویسی
.apkو هم برای لغو برنامه سیستم با نسخه جدیدتری که تحت/dataنصب شده است صادق است. - اگر دو یا چند برنامه بخواهند شناسه کاربری را همرسانی کنند (تا بتوانند دادهها و غیره را همرسانی کنند)، باید با کلید یکسانی امضا شوند.
- وقتی برنامهای جایگزین میشود، باید با همان کلید برنامه قدیمی امضا شود تا بتواند به دادههای برنامه قدیمی دسترسی پیدا کند. این موضوع هم برای بهروزرسانی برنامههای کاربر با بازنویسی
- بستههای بهروزرسانی OTA باید با یکی از کلیدهای موردانتظار سیستم امضا شوند، درغیراینصورت فرایند نصب آنها را رد خواهد کرد.
کلیدهای انتشار
درخت Android شامل test-keys در
build/target/product/security است. ساختن تصویر سیستمعامل Android
بااستفاده از make همه فایلهای .apk را بااستفاده از
کلیدهای آزمایشی امضا میکند. ازآنجاییکه کلیدهای آزمایشی بهصورت عمومی شناختهشده هستند، هر کسی میتواند فایلهای .apk خود را با همان کلیدها امضا کند، که ممکن است به آنها اجازه دهد برنامههای سیستم را که در تصویر سیستمعامل شما ساخته شدهاند جایگزین یا ربوده کنند. به همین دلیل، بسیار مهم است که هر تصویر سیستمعامل Android که بهطور عمومی منتشر یا مستقر میشود با مجموعه ویژهای از کلیدهای انتشار که فقط شما به آنها دسترسی دارید امضا شود.
برای تولید مجموعه کلیدهای انتشار منحصربهفرد خودتان، این فرمانها را از ریشه درخت Android اجرا کنید:
subject='/C=US/ST=California/L=Mountain View/O=Android/OU=Android/CN=Android/emailAddress=android@android.com'mkdir ~/.android-certsfor x in releasekey platform shared media networkstack; do \ ./development/tools/make_key ~/.android-certs/$x "$subject"; \ done
$subject باید تغییر کند تا اطلاعات سازمانتان را منعکس کند. میتوانید از هر دایرکتوری استفاده کنید، اما دقت کنید که
مکان پشتیبانگیریشده و امنی را انتخاب کنید. برخیاز فروشندگان انتخاب میکنند که کلید خصوصی خود را با یک گذرعبارت قوی رمزگذاری کنند و کلید رمزگذاریشده را در کنترل منبع ذخیره کنند؛ برخی دیگر کلیدهای انتشار خود را در جایی کاملاً متفاوت ذخیره میکنند، مثلاً در رایانهای که به اینترنت متصل نیست.
برای تولید تصویر نسخه پخش، از این استفاده کنید:
make distsign_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 فایلهای هدف .zip را بهعنوان ورودی میگیرد و فایلهای هدف جدیدی .zip تولید میکند که در آن همه فایلهای .apk با کلیدهای جدید امضا شدهاند. تصاویر جدیداً امضاشده را میتوانید در IMAGES/ در signed-target_files.zip پیدا کنید.
امضا کردن بستههای OTA
فایل zip هدف-فایلهای امضاشده را میتوان بااستفاده از روش زیر به فایل zip بهروزرسانی ازطریق هوا امضاشده تبدیل کرد:
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
(بهطور پیشفرض)، بررسی میکند. «بازیابی» امضا را با کلیدهای عمومی ذخیرهشده در
دیسک RAM پارتیشن بازیابی، در فایل /res/keys، بررسی میکند.
بهطور پیشفرض، فایلهای هدف .zip تولیدشده توسط مجموعههای ساخت، گواهینامه
OTA را تنظیم میکند تا با کلید آزمایشی مطابقت داشته باشد. در تصویر منتشرشده، باید از گواهینامه دیگری استفاده شود تا دستگاهها بتوانند اصالت بسته بهروزرسانی را تأیید کنند. ارسال پرچم -o به
sign_target_files_apks، همانطور که در بخش قبلی نشان داده شده است،
گواهی کلید آزمایشی را با گواهی کلید انتشار از فهرست راهنمای گواهیهای شما
جایگزین میکند.
معمولاً تصویر سیستم و روگرفت بازیابی مجموعه یکسانی از کلیدهای عمومی 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 است. کلید خصوصی باید محرمانه نگه داشته شود و برای امضا کردن بسته لازم است. خود کلید ممکن است با گذرواژه محافظت شود. گواهینامه، درمقابل، فقط حاوی بخش عمومی کلید است، بنابراین میتواند بهطور گسترده توزیع شود. از آن برای درستیسنجی اینکه بسته با کلید خصوصی مربوطه امضا شده است استفاده میشود.
ساخت استاندارد Android از پنج کلید استفاده میکند که همه آنها در
build/target/product/security قرار دارند:
- کلید آزمایشی
- کلید پیشفرض عمومی برای بستههایی که کلید دیگری برای آنها مشخص نشده است.
- پلتفورم
- کلید آزمایشی برای بستههایی که بخشی از پلاتفرم اصلی هستند.
- همرسانیشده
- کلید آزمایشی برای مواردی که در فرایند خانه/مخاطبین همرسانی میشوند.
- رسانه
- کلید آزمایشی برای بستههایی که بخشی از سیستم رسانه/بارگیری هستند.
بستههای تکی یکی از این کلیدها را با تنظیم LOCAL_CERTIFICATE در فایل Android.mk خود مشخص میکنند. (اگر این متغیر تنظیم نشده باشد، از testkey استفاده میشود.) همچنین میتوانید
کلید کاملاً متفاوتی را براساس نام مسیر مشخص کنید، برای مثال:
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های مشخصشده
بهعنوان ازپیش امضاشده رفتار میکند.
برای محصول فرضی تاردیز، به شش کلید محافظتشده با گذرواژه نیاز دارید:
پنج کلید برای جایگزینی پنج کلید در 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
Android 10 قالب فایل APEX را برای نصب واحدهای سیستم سطح پایین معرفی میکند. همانطور که در امضای APEX توضیح داده شده است، هر فایل APEX با دو کلید امضا میشود: یکی برای تصویر سیستم فایل کوچک درون APEX و دیگری برای کل APEX.
هنگام امضا کردن برای انتشار، دو کلید امضا برای فایل APEX با کلیدهای انتشار جایگزین میشوند. کلید بار داده سیستم فایل با پرچم --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 امضاکننده فیلمنامه شرح ساخت و اثر انگشت را در فایلهای ویژگی ساخت بازنویسی میکند تا نشان دهد ساخت یک ساخت امضاشده است. پرچم --tag_changes کنترل میکند که چه ویرایشهایی
روی اثر انگشت انجام شود. برای دیدن اسناد مربوط به همه پرچمها،
اسکریپت را با -h اجرا کنید.
تولید دستی کلیدها
Android از کلیدهای RSA ۲۰۴۸ بیتی با توان عمومی ۳ استفاده میکند. میتوانید جفتهای گواهینامه/کلید خصوصی را بااستفاده از ابزار openssl از openssl.org تولید کنید:
# generate RSA keyopenssl genrsa -3 -out temp.pem 2048Generating RSA private key, 2048 bit long modulus ....+++ .....................+++ e is 3 (0x3) # create a certificate with the public part of the keyopenssl 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 keyopenssl pkcs8 -in temp.pem -topk8 -outform DER -out releasekey.pk8 -nocrypt# securely delete the temp.pem fileshred --remove temp.pem
دستور openssl pkcs8 که در بالا داده شده است یک فایل pk8 .با بدون
گذرواژه ایجاد میکند که برای استفاده با سیستم ساخت مناسب است. برای ایجاد فایل .pk8 ایمنشده با گذرواژه (که باید برای همه کلیدهای انتشار واقعی انجام دهید)،
آرگومان -nocrypt را با -passout stdin جایگزین کنید؛ سپس openssl
کلید خصوصی را با گذرواژهای که از ورودی استاندارد خوانده میشود رمزگذاری میکند. پیاموارهای چاپ نمیشود، بنابراین اگر stdin ترمینال باشد، برنامه بهنظر میرسد که معلق است، درحالیکه درواقع فقط منتظر است تا گذرواژه را وارد کنید. از مقادیر دیگر میتوان برای
پارامتر -passout استفاده کرد تا گذرواژه از مکانهای دیگر خوانده شود؛ برای
جزئیات، به
اسناد openssl مراجعه کنید.
فایل واسطه temp.pem حاوی کلید خصوصی بدون هیچگونه محافظت گذرواژه است، بنابراین هنگام تولید کلیدهای نسخه پخش، آن را با دقت دور بیندازید. بهطور خاص، ابزار GNUshred ممکن است در شبکهها یا سیستمهای فایل ثبتشده مؤثر نباشد. هنگام تولید کلیدها، میتوانید از دایرکتوری کاری واقع در دیسک RAM (مانند پارتیشن tmpfs) استفاده کنید تا مطمئن شوید که واسطهها بهطور ناخواسته فاش نمیشوند.
ایجاد فایلهای تصویر
وقتی signed-target_files.zip را دارید، باید
تصویر را بسازید تا بتوانید آن را در دستگاه قرار دهید.
برای ایجاد تصویر امضاشده از فایلهای هدف،
فرمان زیر را از ریشه درخت Android
اجرا کنید:
img_from_target_files signed-target_files.zip signed-img.zip
signed-img.zip، حاوی همه .img فایل است.
برای بار کردن تصویر در دستگاه، از fastboot بهصورت زیر استفاده کنید:
fastboot update signed-img.zip