APK सिग्नेचर स्कीम v2

APK सिग्नेचर स्कीम v2, पूरी फ़ाइल के लिए सिग्नेचर स्कीम है. इससे पुष्टि की स्पीड बढ़ती है और APK के सुरक्षित हिस्सों में हुए किसी भी बदलाव का पता चलता है. इससे पूरी सुरक्षा की गारंटी को बेहतर बनाया जाता है.

APK सिग्नेचर स्कीम v2 का इस्तेमाल करके साइन करने पर, ZIP सेंट्रल डायरेक्ट्री सेक्शन से ठीक पहले APK फ़ाइल में APK साइनिंग ब्लॉक शामिल किया जाता है. APK साइनिंग ब्लॉक में, v2 सिग्नेचर और साइन करने वाले की पहचान की जानकारी को APK सिग्नेचर स्कीम v2 ब्लॉक में सेव किया जाता है.

साइन करने से पहले और बाद में APK

पहली इमेज. साइन करने से पहले और बाद में APK

APK सिग्नेचर स्कीम v2 को Android 7.0 (Nougat) में लॉन्च किया गया था. Android 6.0 (Marshmallow) और उससे पहले के वर्शन वाले डिवाइसों पर APK इंस्टॉल करने के लिए, v2 स्कीम से साइन करने से पहले, APK को JAR साइनिंग का इस्तेमाल करके साइन किया जाना चाहिए.

APK साइनिंग ब्लॉक

v1 APK फ़ॉर्मैट के साथ पुराने सिस्टम के साथ काम करने के लिए, v2 और उसके बाद के APK हस्ताक्षरों को APK साइनिंग ब्लॉक में सेव किया जाता है. APK हस्ताक्षर स्कीम v2 के लिए एक नया कंटेनर लॉन्च किया गया है. APK फ़ाइल में, APK साइनिंग ब्लॉक, ZIP सेंट्रल डायरेक्ट्री से ठीक पहले होता है. यह फ़ाइल के आखिर में होता है.

ब्लॉक में आईडी-वैल्यू पेयर इस तरह से रैप किए गए हैं कि APK में ब्लॉक को आसानी से ढूंढा जा सके. APK के v2 हस्ताक्षर को आईडी-वैल्यू पेयर के तौर पर सेव किया जाता है, जिसका आईडी 0x7109871a है.

फ़ॉर्मैट करें

APK साइनिंग ब्लॉक का फ़ॉर्मैट इस तरह है (सभी संख्या वाले फ़ील्ड छोटे-छोटे होते हैं):

  • size of block बाइट में (इस फ़ील्ड को छोड़कर) (uint64)
  • uint64-length-prefixed आईडी-वैल्यू पेयर का क्रम:
    • ID (uint32)
    • value (वैरिएबल-लेंथ: पेयर की लंबाई - 4 बाइट)
  • size of block बाइट में—यह पहले फ़ील्ड (uint64) जैसा ही है
  • magic “APK सिग ब्लॉक 42” (16 बाइट)

APK को पार्स करने के लिए, सबसे पहले ZIP सेंट्रल डायरेक्ट्री की शुरुआत का पता लगाया जाता है. इसके लिए, फ़ाइल के आखिर में मौजूद सेंट्रल डायरेक्ट्री के आखिर में मौजूद रिकॉर्ड को ढूंढा जाता है. इसके बाद, रिकॉर्ड से सेंट्रल डायरेक्ट्री के शुरू होने का ऑफ़सेट पढ़ा जाता है. magic वैल्यू से यह पता चलता है कि सेंट्रल डायरेक्ट्री से पहले, APK साइनिंग ब्लॉक है या नहीं. इसके बाद, size of block वैल्यू फ़ाइल में ब्लॉक की शुरुआत पर ले जाती है.

ब्लॉक का विश्लेषण करते समय, ऐसे आईडी-वैल्यू पेयर को अनदेखा किया जाना चाहिए जिनके आईडी की पहचान नहीं की जा सकी है.

APK सिग्नेचर स्कीम v2 ब्लॉक

APK पर हस्ताक्षर करने वाले एक या उससे ज़्यादा लोग/पहचान लोग साइन करते हैं. हर व्यक्ति को साइनिंग पासकोड से दिखाया जाता है. यह जानकारी, APK सिग्नेचर स्कीम v2 ब्लॉक के तौर पर सेव की जाती है. हस्ताक्षर करने वाले हर व्यक्ति के लिए, यह जानकारी सेव की जाती है:

  • (हस्ताक्षर एल्गोरिदम, डाइजेस्ट, हस्ताक्षर) टपल. डाइजेस्ट को इस तरह सेव किया जाता है कि APK के कॉन्टेंट की इंटिग्रिटी जांच करने से, हस्ताक्षर की पुष्टि में कमी आती है.
  • हस्ताक्षर करने वाले व्यक्ति की पहचान दिखाने वाली X.509 सर्टिफ़िकेट चेन.
  • की-वैल्यू पेयर के तौर पर अन्य एट्रिब्यूट.

साइन करने वाले हर व्यक्ति के लिए, APK की पुष्टि की जाती है. इसके लिए, दी गई सूची में मौजूद ऐसे सिग्नेचर का इस्तेमाल किया जाता है जो काम करता हो. जिन हस्ताक्षरों के बारे में जानकारी नहीं है उन्हें अनदेखा कर दिया जाता है. यह हर तरीके पर निर्भर करता है कि इस्तेमाल किए जाने वाले एक से ज़्यादा हस्ताक्षर मिलने पर किस हस्ताक्षर का इस्तेमाल किया जाए. इससे आने वाले समय में, पुराने सिस्टम के साथ काम करने के तरीके से हस्ताक्षर करने के ज़्यादा मज़बूत तरीकों के बारे में बताया जा सकेगा. हमारा सुझाव है कि सबसे मज़बूत सिग्नेचर की पुष्टि करें.

फ़ॉर्मैट करें

APK सिग्नेचर स्कीम v2 ब्लॉक, APK साइनिंग ब्लॉक में आईडी 0x7109871a के नीचे सेव होता है.

APK सिग्नेचर स्कीम v2 ब्लॉक का फ़ॉर्मैट इस तरह का है (सभी संख्या वाली वैल्यू, लिटल-इंडियन फ़ॉर्मैट में होती हैं. लंबाई के प्रीफ़िक्स वाले सभी फ़ील्ड, लंबाई के लिए uint32 का इस्तेमाल करते हैं):

  • लंबाई के प्रीफ़िक्स वाले signer का लंबाई के प्रीफ़िक्स वाला क्रम:
    • लंबाई के प्रीफ़िक्स वाला signed data:
      • लंबाई के प्रीफ़िक्स वाले digests का लंबाई के प्रीफ़िक्स वाला क्रम:
      • X.509 certificates का लंबाई-प्रीफ़िक्स वाला क्रम:
        • X.509 certificate की लंबाई का प्रीफ़िक्स (ASN.1 DER फ़ॉर्म)
      • लंबाई-प्रीफ़िक्स additional attributes का लंबाई-प्रीफ़िक्स वाला क्रम:
        • ID (uint32)
        • value (वैरिएबल-लेंथ: अन्य एट्रिब्यूट की लंबाई - 4 बाइट)
    • लंबाई-प्रीफ़िक्स signatures का लंबाई-प्रीफ़िक्स वाला क्रम:
      • signature algorithm ID (uint32)
      • लंबाई के प्रीफ़िक्स signature, signed data से ज़्यादा
    • लंबाई के प्रीफ़िक्स वाला public key (SubjectPublicKeyInfo, ASN.1 DER फ़ॉर्म)

हस्ताक्षर के एल्गोरिदम के आईडी

  • 0x0101—SHA2-256 डाइजेस्ट, SHA2-256 MGF1, 32 बाइट का साल्ट, ट्रेलर: 0xbc के साथ RSASSA-PSS
  • 0x0102—SHA2-512 डाइजेस्ट के साथ आरएसएएसएसए-पीएसएस, SHA2-512 MGF1, 64 बाइट सॉल्ट, ट्रेलर: 0xbc
  • 0x0103—SHA2-256 डाइजेस्ट के साथ RSASSA-PKCS1-v1_5. यह बिल्ड सिस्टम के लिए है, जिनके लिए डिटरमिनिस्टिक सिग्नेचर की ज़रूरत होती है.
  • SHA2-512 डाइजेस्ट के साथ 0x0104—RSASSA-PKCS1-v1_5. यह उन बिल्ड सिस्टम के लिए है जिनमें डिटरमिनिस्टिक हस्ताक्षर की ज़रूरत होती है.
  • 0x0201—SHA2-256 डाइजेस्ट के साथ ईसीडीए
  • 0x0202—SHA2-512 डाइजेस्ट के साथ ECDSA
  • 0x0301—SHA2-256 डाइजेस्ट के साथ डीएसए

Android प्लैटफ़ॉर्म पर, ऊपर बताए गए सभी हस्ताक्षर एल्गोरिदम काम करते हैं. हस्ताक्षर करने वाले टूल, एल्गोरिदम के सबसेट के साथ काम कर सकते हैं.

इस्तेमाल की जा सकने वाली कुंजियों के साइज़ और ईसी कर्व:

  • आरएसए: 1024, 2048, 4096, 8192, 16384
  • ईसी: एनआईएसटी P-256, P-384, P-521
  • डीएसए: 1024, 2048, 3072

पूरी सुरक्षा देने की सुविधा वाला कॉन्टेंट

APK के कॉन्टेंट को सुरक्षित रखने के लिए, इसमें चार सेक्शन होते हैं:

  1. ZIP एंट्री का कॉन्टेंट (ऑफ़सेट 0 से लेकर APK साइनिंग ब्लॉक की शुरुआत तक)
  2. APK साइनिंग ब्लॉक
  3. ZIP Central Directory
  4. ZIP End of Central Directory

साइन करने के बाद APK के सेक्शन

दूसरी इमेज. साइन करने के बाद APK के सेक्शन

APK सिग्नेचर स्कीम v2, सेक्शन 1, 3, 4, और सेक्शन 2 में मौजूद APK सिग्नेचर स्कीम v2 ब्लॉक के signed data ब्लॉक की सुरक्षा को बनाए रखता है.

सेक्शन 1, 3, और 4 की इंटिग्रिटी को signed data ब्लॉक में सेव किए गए उनके कॉन्टेंट के एक या एक से ज़्यादा डाइजेस्ट से सुरक्षित किया जाता है. इन्हें एक या एक से ज़्यादा हस्ताक्षर से सुरक्षित किया जाता है.

सेक्शन 1, 3, और 4 में डाइजेस्ट की गिनती इस तरह से की गई है, जैसे कि दो लेवल वाले मर्कल ट्री. हर सेक्शन को लगातार 1 एमबी (220 बाइट) के हिस्सों में बांटा जाता है. हर सेक्शन का आखिरी हिस्सा छोटा हो सकता है. हर एक हिस्से के डाइजेस्ट का हिसाब, बाइट 0xa5 की काट-छांट, हिस्से की बाइट में लंबाई (little-endian uint32), और डेटा वाले हिस्से के कॉन्टेंट के आधार पर लगाया जाता है. टॉप-लेवल डाइजेस्ट का हिसाब, बाइट 0x5a, चंक की संख्या (लिटल-इंडियन uint32), और चंक के डाइजेस्ट को जोड़कर लगाया जाता है. यह हिसाब, APK में चंक के दिखने के क्रम में लगाया जाता है. डाइजेस्ट का हिसाब, एक साथ कई हिस्सों में लगाया जाता है, ताकि कैलकुलेशन को तेज़ किया जा सके.

APK डाइजेस्ट

तीसरी इमेज. APK डाइजेस्ट

सेक्शन 4 (ZIP सेंट्रल डायरेक्ट्री का आखिरी हिस्सा) को सुरक्षित करना मुश्किल है, क्योंकि इसमें सेंट्रल डायरेक्ट्री का ऑफ़सेट शामिल होता है. जब APK साइनिंग ब्लॉक का साइज़ बदलता है, तो ऑफ़सेट बदल जाता है. उदाहरण के लिए, जब कोई नया हस्ताक्षर जोड़ा जाता है. इसलिए, ZIP के सेंट्रल डायरेक्ट्री के आखिर में डाइजेस्ट कैलकुलेट करते समय, ZIP सेंट्रल डायरेक्ट्री के ऑफ़सेट वाले फ़ील्ड को APK साइनिंग ब्लॉक के ऑफ़सेट वाले फ़ील्ड के तौर पर माना जाना चाहिए.

रोलबैक से जुड़ी सुरक्षा

हमलावर, v2 से हस्ताक्षर किए गए APK की पुष्टि, v1 से हस्ताक्षर किए गए APK के तौर पर करने की कोशिश कर सकता है. ऐसा उन Android प्लैटफ़ॉर्म पर किया जा सकता है जिन पर v2 से हस्ताक्षर किए गए APK की पुष्टि की जा सकती है. इस हमले को कम करने के लिए, v2 और v1, दोनों वर्शन से साइन किए गए APK में, META-INF/*.SF फ़ाइलों के मुख्य सेक्शन में X-Android-APK-Signed एट्रिब्यूट होना चाहिए. एट्रिब्यूट की वैल्यू, APK सिग्नेचर स्कीम आईडी का कॉमा लगाकर अलग किया गया सेट होता है. इस स्कीम का आईडी 2 होता है. v1 सिग्नेचर की पुष्टि करते समय, APK की पुष्टि करने वाले टूल को उन APK को अस्वीकार करना होगा जिनमें APK सिग्नेचर स्कीम के लिए कोई हस्ताक्षर नहीं है.यह स्कीम, पुष्टि करने वाले टूल के लिए इस सेट में से सबसे सही होती है. जैसे, v2 स्कीम. यह सुरक्षा इस बात पर निर्भर करती है कि कॉन्टेंट META-INF/*.SF फ़ाइलें, वर्शन 1 के हस्ताक्षरों से सुरक्षित हैं. JAR पर हस्ताक्षर किए गए APK की पुष्टि करना सेक्शन देखें.

हमलावर, APK हस्ताक्षर स्कीम v2 ब्लॉक से ज़्यादा सुरक्षित हस्ताक्षर हटाने की कोशिश कर सकता है. इस हमले को कम करने के लिए, हस्ताक्षर करने वाले एल्गोरिदम के आईडी की सूची को signed data ब्लॉक में सेव किया जाता है. इस सूची में मौजूद हर आईडी को हर हस्ताक्षर से सुरक्षित किया जाता है.

पुष्टि करें

Android 7.0 और उसके बाद के वर्शन में, APK की पुष्टि APK सिग्नेचर स्कीम v2+ या JAR साइनिंग (v1 स्कीम) के हिसाब से की जा सकती है. पुराने प्लैटफ़ॉर्म पर v2 सिग्नेचर को अनदेखा किया जाता है और सिर्फ़ v1 सिग्नेचर की पुष्टि की जाती है.

APK हस्ताक्षर की पुष्टि करने की प्रोसेस

चौथी इमेज. APK हस्ताक्षर की पुष्टि करने की प्रक्रिया (नए चरण लाल रंग में)

APK सिग्नेचर स्कीम v2 पुष्टि

  1. APK साइनिंग ब्लॉक का पता लगाएं और पुष्टि करें कि:
    1. APK साइनिंग ब्लॉक के दो साइज़ वाले फ़ील्ड की वैल्यू एक ही होती है.
    2. ZIP सेंट्रल डायरेक्ट्री के ठीक बाद, सेंट्रल डायरेक्ट्री रिकॉर्ड का ZIP End आता है.
    3. ज़िप सेंट्रल डायरेक्ट्री के आखिर में कोई और डेटा नहीं होता.
  2. APK साइनिंग ब्लॉक में, APK सिग्नेचर स्कीम v2 का पहला ब्लॉक ढूंढें. अगर v2 ब्लॉक मौजूद है, तो तीसरे चरण पर जाएं. अगर ऐसा नहीं है, तो v1 स्कीम का इस्तेमाल करके, APK की पुष्टि करें.
  3. APK सिग्नेचर स्कीम v2 ब्लॉक में मौजूद हर signer के लिए:
    1. signatures में से सबसे अच्छा signature algorithm ID चुनें. सुरक्षा के लेवल का क्रम, लागू करने/प्लैटफ़ॉर्म के हर वर्शन पर निर्भर करता है.
    2. public key का इस्तेमाल करके, signatures के साथ signature की पुष्टि करें.signed data (signed data को पार्स करना अब सुरक्षित है.)
    3. पुष्टि करें कि digests और signatures में, हस्ताक्षर एल्गोरिदम आईडी की क्रम से लगाई गई सूची एक जैसी हो. (इससे हस्ताक्षर हटाने/जोड़ने से रोका जा सकता है.)
    4. हस्ताक्षर एल्गोरिदम के लिए इस्तेमाल किए गए डाइजेस्ट एल्गोरिदम के समान डाइजेस्ट एल्गोरिदम का इस्तेमाल करके APK की सामग्री के डाइजेस्ट का हिसाब लगाएं.
    5. पुष्टि करें कि कैलकुलेट किया गया डाइजेस्ट, digests के digest से मेल खाता हो.
    6. पुष्टि करें कि certificates के पहले certificate का SubjectPublicKeyInfo, public key से मेल खाता हो.
  4. अगर कम से कम एक signer मिला और मिले हुए हर signer के लिए तीसरे चरण की पुष्टि हो गई, तो पुष्टि हो जाती है.

ध्यान दें: अगर तीसरे या चौथे चरण में कोई गड़बड़ी होती है, तो APK की पुष्टि v1 स्कीम का इस्तेमाल करके नहीं की जानी चाहिए.

JAR से साइन किए गए APK की पुष्टि करना (v1 स्कीम)

हस्ताक्षर किए गए JAR फ़ॉर्मैट में APK, हस्ताक्षर किए गए स्टैंडर्ड JAR फ़ॉर्मैट होता है. इसमें META-INF/MANIFEST.MF में दी गई एंट्री ही होनी चाहिए. साथ ही, सभी एंट्री पर एक ही व्यक्ति या ग्रुप ने हस्ताक्षर किए होने चाहिए. इसकी पुष्टि इस तरह की जाती है:

  1. हस्ताक्षर करने वाले हर व्यक्ति को META-INF/<signer>.SF और META-INF/<signer>.(RSA|DSA|EC) JAR एंट्री से दिखाया जाता है.
  2. <signer>.(RSA|DSA|EC) एक ऐसा PKCS #7 CMS ContentInfo है जिसमें SignedData स्ट्रक्चर है. इस हस्ताक्षर की पुष्टि, <signer>.SF फ़ाइल से की जाती है.
  3. <signer>.SF फ़ाइल में META-INF/MANIFEST.MF की पूरी फ़ाइल डाइजेस्ट होती है और META-INF/MANIFEST.MF के हर सेक्शन के डाइजेस्ट शामिल हैं. MANIFEST.MF की पूरी फ़ाइल के डाइजेस्ट की पुष्टि की गई हो. अगर ऐसा नहीं हो पाता है, तो हर MANIFEST.MF सेक्शन के डाइजेस्ट की पुष्टि की जाएगी.
  4. META-INF/MANIFEST.MF में, पूरी सुरक्षा वाली हर JAR एंट्री के लिए, एक ऐसा सेक्शन होता है जिसका नाम एंट्री के नाम से मिलता-जुलता होता है. इसमें एंट्री के अनकंप्रेस किए गए कॉन्टेंट का डाइजेस्ट होता है. इन सभी डाइजेस्ट की पुष्टि की गई है.
  5. अगर APK में ऐसी JAR एंट्री शामिल हैं जो MANIFEST.MF में शामिल नहीं हैं और JAR सिग्नेचर का हिस्सा नहीं हैं, तो APK की पुष्टि नहीं हो पाती.

इसलिए, सुरक्षा चेन में <signer>.(RSA|DSA|EC) -> <signer>.SF -> MANIFEST.MF -> हर इंटिग्रिटी-सुरक्षित JAR एंट्री का कॉन्टेंट शामिल होता है.