Code Signing (امضای کد) — مکانیزم امضای دیجیتال فایلهای اجرایی است که اصالت توسعهدهنده و یکپارچگی برنامه را تضمین میکند. در اندروید، هر فایل APK قبل از نصب روی دستگاه یا انتشار در Google Play باید با گواهی امضا شود. به گزارش Google, 2024، اندروید از چهار نسل طرح امضا پشتیبانی میکند: از v1 مبتنی بر JAR تا v4 برای نصب جریانی.
نکات اصلی
Code Signing — فرآیند رمزنگاری است که در آن توسعهدهنده کد اجرایی را با گواهی دیجیتال خود امضا میکند. امضا با استفاده از رمزنگاری نامتقارن ایجاد میشود: با کلید خصوصی توسعهدهنده یک امضای دیجیتال تولید میشود و کلید عمومی در گواهی جاسازی میشود. هر کسی میتواند با استفاده از کلید عمومی امضا را تأیید کند، اما تغییر کد بدون نقض امضا غیرممکن است.
در توسعه موبایل امضای کد سه وظیفه را انجام میدهد. اول — احراز هویت: کاربر و پلتفرم میتوانند توسعهدهنده برنامه را شناسایی کنند. دوم — یکپارچگی: هر تغییری در APK پس از امضا، امضا را باطل میکند. سوم — بهروزرسانی مطمئن: پلتفرم اجازه میدهد برنامه فقط با آن APKهایی بهروز شود که با همان گواهی نسخه نصبشده امضا شدهاند.
امضای دیجیتال برنامههای اندروید دارای اهمیت حقوقی است. مطابق با قوانین فدراسیون روسیه (63-FZ) و eIDAS اروپا، امضای الکترونیکی واجد شرایط معادل امضای دستی است. با این حال، امضای APK با استفاده از گواهی خودامضا (روش معمول در اندروید) واجد شرایط نیست — یکپارچگی را تأیید میکند، اما هویت توسعهدهنده را از نظر حقوقی اثبات نمیکند.
اندروید از چهار طرح امضای APK پشتیبانی میکند که هرکدام مشکلات نسخه قبلی را حل کرده و قابلیتهای جدیدی اضافه میکنند. همه طرحها میتوانند در یک APK همزیستی داشته باشند — این برای سازگاری با نسخههای قدیمی اندروید ضروری است.
طرح v1 (JAR signing) در اندروید 1.0 ظاهر شد. این طرح فایلهای جداگانه داخل بایگانی APK را از طریق ورودیهای META-INF/MANIFEST.MF امضا میکند. نقطه ضعف: میتوان APK را تغییر داد (فایلها را اضافه یا حذف کرد) و فقط فایلهای تغییر یافته را دوباره امضا کرد، بدون دست زدن به امضای بقیه. این v1 را در برابر برخی حملات آسیبپذیر میکند. طرح v2 (APK Signature Scheme) که در اندروید 7.0 معرفی شد، کل فایل APK را به طور کامل امضا میکند، شامل تمام بایتها به جز خود امضا، که امکان تغییر انتخابی را از بین میبرد.
| طرح | اندروید | ویژگی | چرخش کلید |
|---|---|---|---|
| v1 (JAR) | 1.0+ | امضای هر فایل | خیر |
| v2 | 7.0+ | امضای کل APK | خیر |
| v3 | 9.0+ | امضا + چرخش | بله |
| v4 | 11.0+ | جریانی + ADB | بله |
طرح v3 که در اندروید 9.0 معرفی شد، مشکل دیرینه را حل میکند: اگر کلید امضا به خطر بیفتد یا منقضی شود چه باید کرد؟ قبلاً تغییر کلید امضا به این معنی بود که برنامه جدید تلقی میشود — نمیتوان آن را روی نسخه موجود نصب کرد. v3 مکانیزم چرخش را اضافه میکند: میتوان اثبات تغییر کلید (proof-of-rotation) را که با کلید قدیمی امضا شده است، در APK گنجاند. سیستم زنجیره را بررسی کرده و اجازه بهروزرسانی برنامه امضا شده با کلید جدید را میدهد.
Keystore — محفظه محافظتشده حاوی کلیدهای خصوصی و گواهیها برای امضای برنامهها. در توسعه اندروید از فرمت JKS (Java KeyStore) یا PKCS12 استفاده میشود. Keystore با ابزار keytool که بخشی از JDK است ایجاد میشود. هر کلید در مخزن با یک نام مستعار (alias) شناسایی و با رمز عبور محافظت میشود.
گواهی در keystore شامل کلید عمومی و اطلاعات مالک: نام سازمان، کشور، مدت اعتبار است. برای برنامههای اندروید، گواهی میتواند خودامضا باشد — Google به مرکز صدور گواهی (CA) نیاز ندارد که اندروید را از iOS متمایز میکند. با این حال، مدت اعتبار گواهی باید حداقل 25 سال باشد، زیرا برنامه با همان کلید بهروزرسانی میشود.
# ایجاد keystore جدید برای امضا
keytool -genkey -v -keystore my-release.keystore \
-alias my-app-alias \
-keyalg RSA \
-keysize 2048 \
-validity 10000
# مشاهده محتوای keystore
keytool -list -v -keystore my-release.keystore
اندروید از دو الگوریتم برای کلیدهای امضا پشتیبانی میکند: RSA و ECDSA. RSA با اندازه کلید 2048 بیت — استاندارد دوفاکتو که توسط تمام نسخههای اندروید پشتیبانی میشود. ECDSA (الگوریتم امضای دیجیتال منحنی بیضوی) با منحنی P-256 قدرت رمزنگاری یکسانی را با اندازه کلید کوچکتر فراهم میکند. از اندروید 9.0 به بعد توصیه میشود از ECDSA استفاده شود زیرا در تأیید روی دستگاههای موبایل سریعتر است.
در Android Gradle Plugin امضا از طریق بلوک signingConfigs در build.gradle سطح ماژول پیکربندی میشود. برای بیلدهای debug، Android Studio به طور خودکار یک keystore اشکالزدایی با رمزهای عبور شناختهشده ایجاد میکند. برای بیلدهای release، توسعهدهنده مسیر keystore خود، نام مستعار کلید و رمزهای عبور را مشخص میکند. توصیه میشود رمزهای عبور را در فایلهای پیکربندی جداگانه که از سیستم کنترل نسخه خارج شدهاند ذخیره کنید.
روش مدرن مدیریت متمرکز امضا از طریق CI/CD است. Jenkins، GitLab CI یا GitHub Actions میتوانند keystore را به عنوان مصنوع محافظتشده و رمزهای عبور را در اسرار محیط ذخیره کنند. این کار از نشت کلیدها از طریق مخزن جلوگیری کرده و تغییر کلید را در صورت لزوم ساده میکند.
// build.gradle (سطح ماژول) — پیکربندی امضا
android {
signingConfigs {
release {
storeFile file("my-release.keystore")
storePassword System.getenv("KEYSTORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
برای حداکثر سازگاری، APK باید با هر سه طرح (v1 + v2 + v3) امضا شود. Android Gradle Plugin به طور پیشفرض همه طرحها را شامل میشود. APK امضا شده فقط با v2 روی اندروید 6.0 و پایینتر نصب نمیشود. APK فقط با v1 مزایای یکپارچگی v2 را در اندروید 7.0+ نخواهد داشت. گنجاندن همه طرحها اندازه APK را بیش از 1–2% افزایش نمیدهد و سازگاری با هر دستگاهی را تضمین میکند.
Play App Signing — سرویس Google Play که به طور متمرکز کلیدهای امضای برنامهها را مدیریت میکند. توسعهدهنده APK امضا شده با کلید آپلود (upload key) را به Google Play Console آپلود میکند و Google Play قبل از تحویل به کاربران آن را با کلید توزیع (distribution key) دوباره امضا میکند. این کار از کلید توزیع در برابر گم شدن یا به خطر افتادن محافظت میکند.
مزایای Play App Signing: امنیت — کلید توزیع در مخزن محافظتشده Google ذخیره میشود؛ چرخش — میتوان از طریق کنسول درخواست تغییر کلید داد؛ بازیابی — در صورت گم شدن کلید آپلود میتوان یک کلید جدید تولید کرد. نقطه ضعف: برای برنامههایی که قبل از پیادهسازی Play App Signing وجود داشتهاند، انتقال نیاز به ایجاد یک برنامه جدید دارد زیرا کلید توزیع قدیمی قبلاً استفاده میشود.
# دریافت اثر انگشت گواهی (SHA-256)
keytool -list -v -keystore my-release.keystore \
-alias my-app-alias | grep "SHA256"
# بررسی امضای APK با apksigner
apksigner verify --verbose app-release.apk
اگر کلید امضا گم شود و Play App Signing استفاده نشود، بازیابی امکان بهروزرسانی برنامه غیرممکن است — باید یک برنامه جدید با نام بسته جدید ایجاد کنید. این یکی از دلایل اصلی استفاده از Play App Signing است. Google توصیه میکند یک نسخه پشتیبان از keystore در انبار آفلاین محافظتشده (حافظه USB رمزگذاریشده، صندوق امانات بانکی) نگهداری کنید.
در هنگام نصب APK، اندروید تأیید امضا را در چند مرحله انجام میدهد. اول — بررسی گواهی: آیا منقضی نشده است، آیا فرمت درست است. دوم — بررسی امضا: آیا امضای رمزنگاری با محتوای APK مطابقت دارد. سوم — مقایسه گواهی با نسخه نصبشده: اگر برنامه قبلاً روی دستگاه وجود دارد، گواهی باید مطابقت داشته باشد، در غیر این صورت نصب مسدود میشود.
سیستم تأیید در PackageManagerService تعبیه شده است. هنگام پردازش درخواست نصب، PMS امضا را از APK استخراج میکند، آن را با کلاس android.util.PackageParser بررسی میکند و با امضای ذخیره شده برنامه نصبشده (در صورت وجود) مقایسه میکند. در صورت عدم تطابق، کاربر خطای «INSTALL_FAILED_UPDATE_INCOMPATIBLE» را دریافت میکند. این مکانیزم از حملات جایگزینی جلوگیری میکند (بدافزار نمیتواند برنامه قانونی را با نسخه خود بهروز کند).
توسعهدهنده میتواند به طور مستقل امضای APK را با ابزار apksigner از Android SDK Build Tools بررسی کند. دستور apksigner verify --verbose app.apk نشان میدهد APK با کدام طرحها امضا شده، آیا گواهیها معتبر هستند و آیا امضاها با محتوا مطابقت دارند. برای بررسی برنامهای امضای برنامه نصبشده از PackageManager.getPackageInfo() با پرچم GET_SIGNATURES استفاده میشود.
// بررسی برنامهای امضای برنامه نصبشده
fun getAppSignature(context: Context, packageName: String): String? {
val pm = context.packageManager
val info = pm.getPackageInfo(
packageName,
PackageManager.GET_SIGNATURES
)
return info.signatures?.firstOrNull()?.toCharsString()
}
امنیت کلید امضا — جنبه حیاتی توسعه اندروید است. به خطر افتادن کلید به مهاجم اجازه میدهد بهروزرسانیهای برنامه شما را با کد خود امضا کند. قوانین اساسی: هرگز کلید را در مخزن ذخیره نکنید، از یک کلید برای برنامههای مختلف استفاده نکنید، کلید را از طریق کانالهای ناامن (ایمیل، پیامرسان) ارسال نکنید.
روش توصیهشده جداسازی کلیدها است. برای هر برنامه از یک کلید جداگانه و یک کلید جداگانه برای آپلود در Google Play (upload key) استفاده کنید. برای بیلدهای debug، Android Studio یک debug.keystore مشترک ایجاد میکند — نمیتوان از آن برای بیلدهای release استفاده کرد. مدت اعتبار گواهی باید 25–30 سال باشد (استاندارد جاری تأیید شده توسط Google).
| روش | توصیه |
|---|---|
| ذخیره کلید | حافظه رمزگذاریشده، اسرار CI/CD |
| مدت گواهی | حداقل 25 سال |
| الگوریتم | RSA 2048+ یا ECDSA P-256 |
| جداسازی | کلید جداگانه برای هر برنامه |
| پشتیبان | نسخه آفلاین keystore |
به طور منظم یکپارچگی زنجیره امضا را بررسی کنید. هنگام تغییر کارمندانی که به کلیدها دسترسی دارند، upload key را از طریق Google Play Console بهروز کنید. از ابزارهایی مانند Google Play Integrity API برای بررسی اینکه برنامه شما در دستگاههای کاربران دستکاری نشده است استفاده کنید. API دادههایی درباره امضا، یکپارچگی برمیگرداند و آنها را برای تأیید به سرور ارسال میکند.
پرسشهای متداول
Code Signing — امضای دیجیتال فایل APK است که تأیید میکند برنامه توسط یک توسعهدهنده خاص ایجاد شده و پس از امضا تغییری نکرده است. بدون امضا، APK روی دستگاه نصب نمیشود.
از ابزار keytool موجود در JDK استفاده کنید: keytool -genkey -v -keystore my-release.keystore -alias my-alias -keyalg RSA -keysize 2048 -validity 10000. keystore حاصل را در build.gradle در بلوک signingConfigs مشخص کنید.
اگر کلید گم شده باشد و از Play App Signing استفاده نکنید، بهروزرسانی برنامه غیرممکن میشود. باید یک برنامه جدید در Google Play با نام بسته جدید ایجاد کنید. برای محافظت در برابر گم شدن کلید از Play App Signing استفاده کنید.
v1 هر فایل داخل APK را جداگانه امضا میکند — مهاجم میتواند یک فایل را تغییر داده و فقط آن را دوباره امضا کند. v2 کل APK را به طور کامل امضا میکند — هر تغییری امضا را باطل میکند که سطح امنیتی بالاتری را فراهم میکند.
Play App Signing — سرویس Google Play است که کلید توزیع برنامهها را به طور متمرکز ذخیره میکند. توسعهدهنده APK امضا شده با upload key را آپلود میکند و Google آن را قبل از تحویل به کاربران دوباره امضا میکند و از کلید در برابر گم شدن یا سرقت محافظت میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید