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

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

  1. يجب توقيع كل ملف .apk داخل الصورة. يستخدم "مدير الحِزم" في Android توقيع .apk بطريقتَين:
    • عند استبدال تطبيق، يجب توقيعه بالمفتاح نفسه الذي تم توقيع التطبيق القديم به من أجل الوصول إلى بيانات التطبيق القديم. وينطبق ذلك على تحديث تطبيقات المستخدمين من خلال الكتابة فوق .apk، وعلى استبدال تطبيق نظام بإصدار أحدث مثبَّت ضمن /data.
    • إذا أراد تطبيقان أو أكثر مشاركة معرّف مستخدم (ليتمكّنا من مشاركة البيانات وما إلى ذلك)، يجب توقيعهما باستخدام المفتاح نفسه.
  2. يجب توقيع حِزم تحديثات 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
مفتاح تلقائي عام للحِزم التي لا تحدّد مفتاحًا بطريقة أخرى
نظام
مفتاح الاختبار للحِزم التي تشكّل جزءًا من المنصة الأساسية
مشترَكة
مفتاح اختبار للعناصر التي تتم مشاركتها في عملية المنزل/جهات الاتصال
وسائط
مفتاح اختبار للحِزم التي تشكّل جزءًا من نظام الوسائط/التنزيل
networkstack
مفتاح الاختبار للحِزم التي تشكّل جزءًا من نظام الشبكات يُستخدَم مفتاح networkstack لتوقيع الملفات الثنائية المصمَّمة باعتبارها مكوّنات نظام معيارية . إذا تم إنشاء تحديثات الوحدة بشكل منفصل ودمجها كإنشاءات مسبقة في صورة جهازك، قد لا تحتاج إلى إنشاء مفتاح networkstack في شجرة المصدر لنظام Android.

تحدّد الحِزم الفردية أحد هذه المفاتيح من خلال ضبط 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 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