تستخدم صور نظام التشغيل 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-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
ملفات مستهدَفة .zip
كمدخلات وينتج ملفات مستهدَفة .zip
جديدة تم توقيع جميع ملفات .apk
فيها باستخدام مفاتيح جديدة. يمكنك العثور على الصور الموقّعة حديثًا ضمن IMAGES/
في signed-target_files.zip
.
توقيع حِزم OTA
يمكن تحويل ملف ZIP موقّع خاص بملفات الاستهداف إلى ملف ZIP موقّع خاص بتحديث عبر الأثير (OTA) باتّباع الإجراء التالي:
ota_from_target_files \
-k (--package_key)
signed-target_files.zip \
signed-ota_update.zip
التوقيعات والتحميل الجانبي
لا تتجاوز عملية التحميل الجانبي آلية التحقّق العادية من توقيع الحزمة في وضع الاسترداد، إذ يتحقّق وضع الاسترداد قبل تثبيت الحزمة من توقيعها باستخدام أحد المفاتيح الخاصة التي تتطابق مع المفاتيح العامة المخزّنة في قسم الاسترداد، تمامًا كما يحدث مع الحزمة التي يتم تسليمها عبر الأثير.
يتم عادةً التحقّق من حِزم التحديثات التي يتم تلقّيها من النظام الرئيسي مرتين:
مرة واحدة من خلال النظام الرئيسي باستخدام
الطريقة RecoverySystem.verifyPackage()
في واجهة برمجة التطبيقات Android، ثم مرة أخرى من خلال
وضع الاسترداد. تتحقّق واجهة برمجة التطبيقات RecoverySystem من التوقيع مقارنةً بالمفاتيح العامة
المخزَّنة في النظام الرئيسي، في الملف /system/etc/security/otacerts.zip
(تلقائيًا). تتحقّق عملية الاسترداد من التوقيع باستخدام المفاتيح العامة المخزّنة
في قسم الاسترداد على قرص RAM، وذلك في الملف /res/keys
.
تلقائيًا، تحدّد ملفات .zip
المستهدَفة التي تنتجها حِزم الإنشاء شهادة OTA لتتطابق مع مفتاح الاختبار. في صورة الإصدار، يجب استخدام شهادة مختلفة حتى تتمكّن الأجهزة من التحقّق من صحة حزمة التحديث. يؤدي تمرير العلامة -o
إلى sign_target_files_apks
، كما هو موضّح في القسم السابق، إلى استبدال شهادة مفتاح الاختبار بشهادة مفتاح الإصدار من دليل شهاداتك.
عادةً ما تخزِّن صورة النظام وصورة الاسترداد المجموعة نفسها من المفاتيح العامة الخاصة بالتحديث عبر الهواء. من خلال إضافة مفتاح إلى مجموعة مفاتيح الاسترداد فقط، يمكن توقيع الحِزم التي يمكن تثبيتها فقط من خلال التحميل الجانبي (بافتراض أنّ آلية تنزيل تحديث النظام الرئيسي تجري عملية التحقّق بشكل صحيح من ملف 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
:
- testkey
- مفتاح تلقائي عام للحِزم التي لا تحدّد مفتاحًا بطريقة أخرى
- نظام
- مفتاح الاختبار للحِزم التي تشكّل جزءًا من المنصة الأساسية
- مشترَكة
- مفتاح اختبار للعناصر التي تتم مشاركتها في عملية المنزل/جهات الاتصال
- وسائط
- مفتاح اختبار للحِزم التي تشكّل جزءًا من نظام الوسائط/التنزيل
تحدّد الحِزم الفردية أحد هذه المفاتيح من خلال ضبط 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، افترِض أنّ لديك إعداد المفتاح التالي لملفات APEX الخاصة بـ com.android.conscrypt.apex
وcom.android.media.apex
وcom.android.runtime.release.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 بحجم 2048 بت مع الأس العام 3. يمكنك إنشاء أزواج من الشهادات والمفاتيح الخاصة باستخدام أداة openssl من openssl.org باتّباع الخطوات التالية:
# generate RSA keyopenssl 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 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