توقيع النُسخ التجريبية للإصدار

تستخدم صور نظام التشغيل Android توقيعات التشفير في مكانَين:

  1. يجب أن يكون كل ملف .apk داخل الصورة موقَّعًا. يستخدم مدير حزم Android توقيع .apk بطريقتَين:
    • عند استبدال تطبيق، يجب توقيعه بالمفتاح نفسه المستخدَم في التطبيق القديم للوصول إلى بياناته. وينطبق ذلك على حد سواء عند تحديث تطبيقات المستخدمين من خلال استبدال .apk، وعند استبدال تطبيق نظام بإصدار أحدث تم تثبيته ضمن /data.
    • إذا أرادت تطبيقان أو أكثر مشاركة معرّف مستخدم (كي يتمكّنوا من مشاركة data وغيرها)، يجب توقيعهما باستخدام المفتاح نفسه.
  2. يجب توقيع حِزم التحديثات عبر الهواء باستخدام أحد المفاتيح المتوقّعة من النظام، وإلا سترفض عملية التثبيت هذه الحِزم.

مفاتيح الإصدار

تتضمّن شجرة Android مفاتيح الاختبار ضمن 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_from_target_files \
-k  (--package_key) 
signed-target_files.zip \
signed-ota_update.zip

التوقيعات وتحميل التطبيقات من مصدر غير معروف

لا يؤدي تحميل الحِزم من مصدر غير معروف إلى تجاوز آلية التحقّق العادية من توقيع الحِزم في وضع الاسترداد. قبل تثبيت حزمة، سيتحقّق وضع الاسترداد من أنّه تم توقيعها باستخدام أحد المفاتيح الخاصة التي تتطابق مع المفاتيح العامة المخزّنة في قسم الاسترداد، تمامًا كما يحدث مع الحزمة التي يتم تسليمها عبر الهواء.

يتم عادةً التحقّق من حِزم التحديثات التي يتم استلامها من النظام الرئيسي مرّتين: مرّة من خلال النظام الرئيسي باستخدام RecoverySystem.verifyPackage() طريقة في واجهة برمجة تطبيقات Android، ثم مرّة أخرى من خلال recovery. تتحقّق RecoverySystem API من التوقيع مقارنةً بالمفاتيح العامة المخزّنة في النظام الرئيسي، في الملف /system/etc/security/otacerts.zip (تلقائيًا). تتحقّق عملية الاسترداد من التوقيع مقارنةً بالمفاتيح العامة المخزّنة في قرص ذاكرة الوصول العشوائي لقسم الاسترداد، في الملف /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:

testkey
مفتاح تلقائي عام للحِزم التي لا تحدّد مفتاحًا
نظام
مفتاح اختبار للحِزم التي تشكّل جزءًا من المنصة الأساسية:
تمت المشاركة
مفتاح اختبار للعناصر التي تتم مشاركتها في عملية المنزل/جهات الاتصال
وسائط
مفتاح اختبار للحِزم التي تشكّل جزءًا من نظام الوسائط/التنزيل
networkstack
مفتاح اختبار للحِزم التي تشكّل جزءًا من نظام الشبكات يتم استخدام مفتاح networkstack لتوقيع الملفات الثنائية المصمّمة على أنّها مكونات نظام نمطية . إذا تم إنشاء تحديثات الوحدات بشكل منفصل ودمجها كعناصر مُسبقة الإنشاء في صورة جهازك، قد لا تحتاج إلى إنشاء مفتاح لشبكة الحِزم في شجرة مصدر 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 directory يحتوي على خمسة مفاتيح لاستبدال جميع المفاتيح في 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

يقدّم نظام التشغيل 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

يلغِي الأمر التالي مفاتيح التوقيع الخاصة بملفَي APK 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 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 هو المحطة الطرفية، سيبدو أنّ البرنامج قد توقّف عن العمل بينما يكون في الواقع في انتظارك لإدخال كلمة مرور. يمكن استخدام قيم أخرى لوسيطة -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