CI/CD والنشر على متاجر التطبيقات

أساسيات توقيع التطبيقات: مخازن المفاتيح في أندرويد

15 دقيقة الدرس 1 من 12

أساسيات توقيع التطبيقات: مخازن المفاتيح في أندرويد

قبل توزيع أي تطبيق أندرويد عبر متجر Google Play — أو تثبيته مباشرة على جهاز خارج وضع التصحيح — يجب أن يكون موقعاً رقمياً. يُثبت التوقيع أن ملف APK أو AAB صادر عن طرف موثوق (أنت المطور) ولم يتم العبث به منذ إنشائه. يتناول هذا الدرس كل ما تحتاج معرفته: ما هو مخزن المفاتيح (keystore)، وكيفية إنشائه، وكيفية ضبط الأسماء المستعارة للمفاتيح وكلمات المرور، وكيفية ربط كتلة signingConfigs في Gradle بحيث تُوقَّع بنيات الإصدار تلقائيًا.

ملاحظة: تُوقَّع بنية التصحيح (debug) تلقائيًا بمفتاح تصحيح مشترك تنشئه Android Studio. لا يقبل هذا المفتاح في متجر Play قط. يجب توقيع بنية الإصدار (release) بمخزن المفاتيح الخاص بك قبل رفعها أو تثبيتها على أجهزة المستخدمين النهائيين.

ما هو مخزن المفاتيح؟

مخزن المفاتيح (keystore) هو ملف ثنائي (بامتداد .jks أو .keystore عادةً) يعمل حاوية آمنة. يخزن إدخالاً واحدًا أو أكثر من المفاتيح، يتضمن كل منها مفتاحاً خاصًا وسلسلة شهادات المفتاح العام المرتبطة به. يستخدم أندرويد المفتاح الخاص داخل مخزن المفاتيح لتوقيع APK أو AAB، وتستخدم الأجهزة المفتاح العام المقابل للتحقق من التوقيع عند التثبيت.

  • كلمة مرور مخزن المفاتيح — تحمي ملف مخزن المفاتيح نفسه.
  • الاسم المستعار للمفتاح (key alias) — اسم يمكن قراءته يعرّف إدخال مفتاح محددًا داخل مخزن المفاتيح.
  • كلمة مرور المفتاح — تحمي إدخال المفتاح الفردي (يمكن أن تكون مطابقة لكلمة مرور مخزن المفاتيح، لكن إبقاؤهما منفصلتين أكثر أمانًا).
  • الصلاحية — توصي Google بصلاحية لا تقل عن 25 عامًا لضمان تغطية المفتاح لكامل دورة حياة التطبيق.
تحذير: إذا فقدت ملف مخزن المفاتيح أو نسيت كلمات مروره، فلن تتمكن أبدًا من إنتاج تحديث يقبله أندرويد أو متجر Play لهذا التطبيق. احتفظ بنسخة احتياطية من مخزن المفاتيح في موقعين آمنين ومنفصلين على الأقل فور إنشائه.

إنشاء مخزن المفاتيح باستخدام keytool

يأتي JDK (مجموعة تطوير Java) مع أداة سطر الأوامر keytool التي تُنشئ مخازن المفاتيح وتديرها. نفّذ الأمر التالي في طرفيتك (استبدل العناصر النائبة بقيمك الخاصة):

إنشاء مخزن مفاتيح جديد

keytool -genkey -v \
  -keystore ~/keys/my-release-key.jks \
  -storetype JKS \
  -keyalg RSA \
  -keysize 2048 \
  -validity 10000 \
  -alias my_key_alias

تعني الأعلام ما يلي:

  • -keystore — المسار الذي سيُكتب فيه ملف مخزن المفاتيح الجديد.
  • -storetype JKS — استخدام تنسيق Java KeyStore (مقبول أيضًا: PKCS12).
  • -keyalg RSA و-keysize 2048 — RSA بطول 2048 بت هو الحد الأدنى المقبول من متجر Play.
  • -validity 10000 — صلاحية لمدة تقارب 27 عامًا.
  • -alias — الاسم الذي ستشير إليه في Gradle.

بعد تنفيذ الأمر، سيطلب منك keytool بشكل تفاعلي كلمة مرور مخزن المفاتيح وكلمة مرور المفتاح وحقول الاسم المميز (الاسم الأول والأخير، والمؤسسة، والمدينة، والبلد). أدخل هذه البيانات بدقة — يخزنها متجر Play للتحقق من الهوية.

تخزين بيانات الاعتماد بأمان باستخدام ملف key.properties

كتابة كلمات المرور مباشرةً في build.gradle خطأ أمني جسيم — كل من يستنسخ مستودعك سيحصل على بيانات اعتماد التوقيع. الاتفاقية المتبعة في مجتمع Flutter هي تخزين بيانات الاعتماد في ملف key.properties يقع خارج نطاق التحكم في الإصدار.

android/key.properties

storePassword=yourKeystorePassword
keyPassword=yourKeyPassword
keyAlias=my_key_alias
storeFile=../../keys/my-release-key.jks

أضف key.properties إلى .gitignore فورًا:

.gitignore (قسم أندرويد)

# بيانات اعتماد التوقيع — لا تُودعها في المستودع
key.properties
*.jks
*.keystore

ضبط signingConfigs في build.gradle

افتح android/app/build.gradle. تحتاج إلى (1) تحميل ملف key.properties، و(2) الإعلان عن كتلة signingConfigs، و(3) تطبيق هذا الإعداد على نوع بناء release.

android/app/build.gradle — إعداد التوقيع الكامل

// 1. حمّل key.properties في أعلى الملف، قبل android {}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    // ... compileSdkVersion و defaultConfig وما إلى ذلك الحالية

    // 2. أعلن عن إعداد التوقيع
    signingConfigs {
        release {
            keyAlias     keystoreProperties['keyAlias']
            keyPassword  keystoreProperties['keyPassword']
            storeFile    keystoreProperties['storeFile'] != null
                             ? file(keystoreProperties['storeFile'])
                             : null
            storePassword keystoreProperties['storePassword']
        }
    }

    // 3. طبّقه على نوع بناء release
    buildTypes {
        release {
            signingConfig signingConfigs.release
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                          'proguard-rules.pro'
        }
    }
}
نصيحة: الفحص على القيمة null في storeFile يمنع Gradle من الانهيار على آلات CI حيث قد لا يوجد key.properties. على CI يجب حقن بيانات اعتماد التوقيع عبر متغيرات البيئة أو مديري الأسرار بدلًا من ذلك.

بناء APK أو AAB إصدار موقع

بمجرد ضبط Gradle، نفّذ أحد أوامر Flutter CLI التالية من جذر المشروع:

بناء مخرجات إصدار موقعة

# بناء App Bundle موقع (المفضل لمتجر Play)
flutter build appbundle --release

# بناء APK موقع (للتثبيت المباشر أو Amazon Appstore)
flutter build apk --release

# بناء APK ضخم يحتوي على جميع ABIs (أكبر حجمًا، مفيد لـ sideloading)
flutter build apk --release --split-per-abi

سيُكتب AAB الموقع في build/app/outputs/bundle/release/app-release.aab، والـ APK في build/app/outputs/flutter-apk/app-release.apk. يمكنك التحقق من التوقيع بـ:

التحقق من توقيع المخرج

keytool -printcert -jarfile build/app/outputs/flutter-apk/app-release.apk

Play App Signing مقابل التوقيع الذاتي

يقدم Google Play خدمة Play App Signing حيث تدير Google مفتاح التوقيع النهائي وتقوم أنت فقط برفع مفتاح الرفع (upload key). إذا اشتركت:

  • مفتاح الرفع (الذي تولّده أعلاه) يوقّع الـ AAB الذي ترفعه.
  • تُعيد Google توقيع التطبيق بـ مفتاح توقيع التطبيق قبل توزيعه على الأجهزة.
  • إذا تعرّض مفتاح الرفع للاختراق، يمكنك طلب إعادة تعيين المفتاح. أما إذا وقّعت بنفسك وفقدت المفتاح، فتطبيقك لا يمكن إصداره نهائيًا.
ملخص: توقيع التطبيقات إلزامي لبنيات الإصدار على أندرويد. استخدم keytool لإنشاء مخزن مفاتيح .jks، وخزّن بيانات الاعتماد في ملف key.properties مدرج في gitignore، وأعلن عن كتلة signingConfigs في build.gradle تقرأ من هذا الملف، ونفّذ flutter build appbundle --release لإنتاج AAB موقع جاهز لمتجر Play. احتفظ بنسخة احتياطية من مخزن المفاتيح فورًا.