APK हस्ताक्षर योजना v3

एंड्रॉइड 9 एपीके कुंजी रोटेशन का समर्थन करता है, जो ऐप्स को एपीके अपडेट के हिस्से के रूप में अपनी साइनिंग की को बदलने की क्षमता देता है। रोटेशन को व्यावहारिक बनाने के लिए, APK को नई और पुरानी साइनिंग की के बीच विश्वास के स्तर को इंगित करना चाहिए। कुंजी रोटेशन का समर्थन करने के लिए, हमने नई और पुरानी कुंजियों का उपयोग करने की अनुमति देने के लिए एपीके हस्ताक्षर योजना को v2 से v3 में अपडेट किया। V3 एपीके साइनिंग ब्लॉक में समर्थित एसडीके संस्करणों और प्रूफ-ऑफ-रोटेशन संरचना के बारे में जानकारी जोड़ता है।

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

v1 एपीके प्रारूप के साथ पश्च-संगतता बनाए रखने के लिए, v2 और v3 एपीके हस्ताक्षर एक एपीके साइनिंग ब्लॉक के अंदर संग्रहीत किए जाते हैं, जो ज़िप केंद्रीय निर्देशिका से ठीक पहले स्थित होता है।

v3 एपीके साइनिंग ब्लॉक प्रारूप v2 जैसा ही है। एपीके का v3 हस्ताक्षर आईडी 0xf05368c0 आईडी के साथ आईडी-मूल्य जोड़ी के रूप में संग्रहीत किया जाता है।

APK हस्ताक्षर योजना v3 ब्लॉक

V3 योजना को बहुत हद तक v2 योजना के समान बनाया गया है। इसका सामान्य प्रारूप समान है और यह समान हस्ताक्षर एल्गोरिथम आईडी , कुंजी आकार और ईसी वक्र का समर्थन करता है।

हालाँकि, v3 योजना समर्थित SDK संस्करणों और प्रूफ-ऑफ़-रोटेशन संरचना के बारे में जानकारी जोड़ती है।

प्रारूप

एपीके सिग्नेचर स्कीम v3 ब्लॉक आईडी 0xf05368c0 के तहत एपीके साइनिंग ब्लॉक के अंदर संग्रहीत है।

एपीके सिग्नेचर स्कीम v3 ब्लॉक का प्रारूप v2 का है:

  • लंबाई-उपसर्ग signer की लंबाई-उपसर्ग अनुक्रम:
    • लंबाई-उपसर्ग signed data :
      • लंबाई-प्रीफिक्स्ड digests का लंबाई-उपसर्ग अनुक्रम:
        • signature algorithm ID (4 बाइट्स)
        • digest (लंबाई-उपसर्ग)
      • X.509 certificates का लंबाई-उपसर्ग अनुक्रम:
        • लंबाई-उपसर्ग X.509 certificate (ASN.1 DER प्रपत्र)
      • minSDK (uint32) - यदि प्लेटफ़ॉर्म संस्करण इस संख्या से कम है तो इस हस्ताक्षरकर्ता को अनदेखा कर दिया जाना चाहिए।
      • maxSDK (uint32) - यदि प्लेटफ़ॉर्म संस्करण इस संख्या से ऊपर है तो इस हस्ताक्षरकर्ता को अनदेखा किया जाना चाहिए।
      • लंबाई-उपसर्ग additional attributes की लंबाई-उपसर्ग अनुक्रम:
        • ID (uint32)
        • value (चर-लंबाई: अतिरिक्त विशेषता की लंबाई - 4 बाइट्स)
        • ID - 0x3ba06f8c
        • value - प्रूफ-ऑफ-रोटेशन संरचना
    • minSDK (uint32) - हस्ताक्षरित डेटा अनुभाग में minSDK मान का डुप्लिकेट - यदि वर्तमान प्लेटफ़ॉर्म सीमा में नहीं है, तो इस हस्ताक्षर के सत्यापन को छोड़ने के लिए उपयोग किया जाता है। हस्ताक्षरित डेटा मान से मेल खाना चाहिए।
    • maxSDK (uint32) - हस्ताक्षरित डेटा अनुभाग में maxSDK मान का डुप्लिकेट - वर्तमान प्लेटफ़ॉर्म सीमा में नहीं होने पर इस हस्ताक्षर के सत्यापन को छोड़ने के लिए उपयोग किया जाता है। हस्ताक्षरित डेटा मान से मेल खाना चाहिए।
    • लंबाई-उपसर्ग signatures का लंबाई-उपसर्ग अनुक्रम:
      • signature algorithm ID (uint32)
      • signed data पर लंबाई-उपसर्ग signature
    • लंबाई-उपसर्ग public key (SubjectPublicKeyInfo, ASN.1 DER प्रपत्र)

प्रूफ-ऑफ-रोटेशन और आत्म-विश्वसनीय-पुराने-सर्ट संरचनाएं

प्रूफ-ऑफ़ रोटेशन स्ट्रक्चर ऐप्स को उन अन्य ऐप्स पर ब्लॉक किए बिना अपने हस्ताक्षर प्रमाणपत्र को घुमाने की अनुमति देता है जिनके साथ वे संवाद करते हैं। इसे पूरा करने के लिए, ऐप सिग्नेचर में डेटा के दो नए टुकड़े होते हैं:

  • तीसरे पक्ष के लिए दावा कि ऐप के हस्ताक्षर प्रमाण पर भरोसा किया जा सकता है जहां कहीं भी इसके पूर्ववर्तियों पर भरोसा किया जाता है
  • ऐप के पुराने साइनिंग सर्टिफिकेट जिन पर ऐप अभी भी भरोसा करता है

हस्ताक्षरित-डेटा अनुभाग में प्रूफ़-ऑफ़-रोटेशन विशेषता में एक एकल-लिंक्ड सूची होती है, जिसमें प्रत्येक नोड में एक हस्ताक्षर प्रमाणपत्र होता है जिसका उपयोग ऐप के पिछले संस्करणों पर हस्ताक्षर करने के लिए किया जाता है। यह विशेषता रोटेशन के वैचारिक सबूत और स्वयं-विश्वसनीय-पुराने-सर्ट डेटा संरचनाओं को समाहित करने के लिए है। सूची को रूट नोड से संबंधित सबसे पुराने हस्ताक्षर प्रमाणपत्र के साथ संस्करण द्वारा आदेश दिया गया है। प्रूफ-ऑफ-रोटेशन डेटा संरचना प्रत्येक नोड में प्रमाण को सूची में अगले पर हस्ताक्षर करके बनाया गया है, और इस प्रकार प्रत्येक नई कुंजी को इस बात के प्रमाण के साथ जोड़ रहा है कि इसे पुरानी कुंजी के रूप में विश्वसनीय होना चाहिए।

स्व-विश्वसनीय-पुराने-सीर्ट डेटा संरचना का निर्माण प्रत्येक नोड में झंडे जोड़कर किया जाता है जो सेट में इसकी सदस्यता और गुणों को दर्शाता है। उदाहरण के लिए, एक ध्वज मौजूद हो सकता है जो दर्शाता है कि किसी दिए गए नोड पर हस्ताक्षर प्रमाणपत्र Android हस्ताक्षर अनुमति प्राप्त करने के लिए विश्वसनीय है। यह फ़्लैग पुराने प्रमाणपत्र द्वारा हस्ताक्षरित अन्य ऐप्स को अभी भी नए हस्ताक्षर प्रमाणपत्र के साथ हस्ताक्षरित ऐप द्वारा परिभाषित हस्ताक्षर अनुमति प्रदान करने की अनुमति देता है। चूंकि संपूर्ण प्रूफ-ऑफ-रोटेशन विशेषता v3 signer फ़ील्ड के हस्ताक्षरित डेटा अनुभाग में रहती है, यह युक्त एपीके पर हस्ताक्षर करने के लिए उपयोग की जाने वाली कुंजी द्वारा सुरक्षित है।

यह प्रारूप एकाधिक हस्ताक्षर कुंजी और विभिन्न पूर्वजों के हस्ताक्षर प्रमाणपत्रों के अभिसरण को एक (एक सामान्य सिंक में एकाधिक प्रारंभिक नोड्स) से रोकता है।

प्रारूप

प्रूफ-ऑफ-रोटेशन को आईडी 0x3ba06f8c के तहत एपीके सिग्नेचर स्कीम v3 ब्लॉक के अंदर संग्रहीत किया जाता है। इसका प्रारूप है:

  • लंबाई-उपसर्ग levels की लंबाई-उपसर्ग अनुक्रम:
    • लंबाई-उपसर्ग signed data (पिछले प्रमाण द्वारा - यदि मौजूद है)
      • लंबाई-उपसर्ग X.509 certificate (ASN.1 DER प्रपत्र)
      • signature algorithm ID (uint32) - पिछले स्तर में सर्टिफिकेट द्वारा उपयोग किया जाने वाला एल्गोरिथम
    • flags (uint32) - यह संकेत करने वाले झंडे कि यह प्रमाणपत्र स्व-विश्वसनीय-पुराने-सर्ट संरचना में होना चाहिए या नहीं, और किस संचालन के लिए।
    • signature algorithm ID (uint32) - अगले स्तर में हस्ताक्षरित डेटा अनुभाग से मेल खाना चाहिए।
    • उपरोक्त signed data पर लंबाई-उपसर्ग signature

एकाधिक प्रमाणपत्र

एंड्रॉइड वर्तमान में कई प्रमाणपत्रों के साथ हस्ताक्षरित एपीके को एक विशिष्ट हस्ताक्षर पहचान के रूप में शामिल करता है, जिसमें शामिल प्रमाणपत्र शामिल हैं। इस प्रकार, हस्ताक्षरित-डेटा अनुभाग में प्रूफ-ऑफ-रोटेशन विशेषता एक निर्देशित एसाइक्लिक ग्राफ बनाती है, जिसे एक एकल-लिंक्ड सूची के रूप में बेहतर रूप से देखा जा सकता है, जिसमें एक नोड का प्रतिनिधित्व करने वाले किसी दिए गए संस्करण के लिए हस्ताक्षरकर्ताओं के प्रत्येक सेट के साथ। यह प्रूफ-ऑफ-रोटेशन संरचना (नीचे बहु-हस्ताक्षरकर्ता संस्करण) में अतिरिक्त जटिलता जोड़ता है। विशेष रूप से, आदेश देना एक चिंता का विषय बन जाता है। क्या अधिक है, स्वतंत्र रूप से APK पर हस्ताक्षर करना संभव नहीं है, क्योंकि प्रूफ-ऑफ-रोटेशन संरचना में प्रमाणपत्रों के नए सेट पर एक-एक करके हस्ताक्षर करने के बजाय पुराने हस्ताक्षर करने वाले प्रमाणपत्र होने चाहिए। उदाहरण के लिए, कुंजी ए द्वारा हस्ताक्षरित एक एपीके जो दो नई कुंजी बी और सी द्वारा हस्ताक्षरित होना चाहता है, बी हस्ताक्षरकर्ता में ए या बी द्वारा हस्ताक्षर शामिल नहीं हो सकता है, क्योंकि यह बी और सी की तुलना में एक अलग हस्ताक्षर पहचान है। इसका मतलब है कि इस तरह की संरचना के निर्माण से पहले हस्ताक्षरकर्ताओं को समन्वय करना चाहिए।

एकाधिक हस्ताक्षरकर्ता प्रूफ-ऑफ-रोटेशन विशेषता

  • लंबाई-उपसर्ग sets की लंबाई-उपसर्ग अनुक्रम:
    • signed data (पिछले सेट द्वारा - यदि मौजूद है)
      • certificates की लंबाई-उपसर्ग अनुक्रम
        • लंबाई-उपसर्ग X.509 certificate (ASN.1 DER प्रपत्र)
      • signature algorithm IDs (uint32) का क्रम - पिछले सेट के प्रत्येक प्रमाणपत्र के लिए एक, उसी क्रम में।
    • flags (uint32) - झंडे यह दर्शाते हैं कि प्रमाणपत्रों का यह सेट स्व-विश्वसनीय-पुराने-सर्ट संरचना में होना चाहिए या नहीं, और किस संचालन के लिए।
    • लंबाई-उपसर्ग signatures का लंबाई-उपसर्ग अनुक्रम:
      • signature algorithm ID (uint32) - हस्ताक्षरित डेटा अनुभाग से मेल खाना चाहिए
      • उपरोक्त signed data पर लंबाई-उपसर्ग signature

प्रूफ-ऑफ-रोटेशन संरचना में एकाधिक पूर्वज

v3 स्कीम एक ही ऐप के लिए एक ही साइनिंग की में घूमने वाली दो अलग-अलग कुंजियों को भी हैंडल नहीं करती है। यह अधिग्रहण के मामले से अलग है, जहां अधिग्रहण करने वाली कंपनी अनुमतियों को साझा करने के लिए अपनी हस्ताक्षर कुंजी का उपयोग करने के लिए अधिग्रहीत ऐप को स्थानांतरित करना चाहती है। अधिग्रहण को एक समर्थित उपयोग-मामले के रूप में देखा जाता है क्योंकि नए ऐप को इसके पैकेज नाम से अलग किया जाएगा और इसमें अपनी स्वयं की प्रूफ-ऑफ-रोटेशन संरचना हो सकती है। असमर्थित मामला, एक ही ऐप का एक ही प्रमाणपत्र प्राप्त करने के लिए दो अलग-अलग पथ हैं, कुंजी रोटेशन डिज़ाइन में किए गए कई अनुमानों को तोड़ देता है।

सत्यापन

एंड्रॉइड 9 और उच्चतर में, एपीके सिग्नेचर स्कीम v3, v2 स्कीम या v1 स्कीम के अनुसार एपीके को सत्यापित किया जा सकता है। पुराने प्लेटफ़ॉर्म v3 हस्ताक्षरों को अनदेखा करते हैं और v2 हस्ताक्षरों को सत्यापित करने का प्रयास करते हैं, फिर v1.

एपीके हस्ताक्षर सत्यापन प्रक्रिया

चित्र 1. एपीके हस्ताक्षर सत्यापन प्रक्रिया

APK हस्ताक्षर योजना v3 सत्यापन

  1. एपीके साइनिंग ब्लॉक का पता लगाएँ और सत्यापित करें कि:
    1. एपीके साइनिंग ब्लॉक के दो आकार के क्षेत्रों में एक ही मूल्य होता है।
    2. ज़िप सेंट्रल डायरेक्टरी के तुरंत बाद सेंट्रल डायरेक्ट्री रिकॉर्ड का ज़िप एंड होता है।
    3. केंद्रीय निर्देशिका के ज़िप अंत का अधिक डेटा द्वारा अनुसरण नहीं किया जाता है।
  2. एपीके साइनिंग ब्लॉक के अंदर पहले एपीके सिग्नेचर स्कीम v3 ब्लॉक का पता लगाएँ। यदि v3 ब्लॉक मौजूद है, तो चरण 3 पर आगे बढ़ें। अन्यथा, v2 योजना का उपयोग करके एपीके को सत्यापित करने के लिए वापस आएं।
  3. एपीके सिग्नेचर स्कीम v3 ब्लॉक में प्रत्येक signer के लिए एक न्यूनतम और अधिकतम एसडीके संस्करण है जो वर्तमान प्लेटफॉर्म की सीमा में है:
    1. सिग्नेचर से सबसे मजबूत समर्थित signatures signature algorithm ID चुनें। स्ट्रेंथ ऑर्डरिंग प्रत्येक कार्यान्वयन/प्लेटफ़ॉर्म संस्करण पर निर्भर है।
    2. public key का उपयोग करके signed data के विरुद्ध signatures से संबंधित signature सत्यापित करें। (अब signed data को पार्स करना सुरक्षित है।)
    3. सत्यापित करें कि हस्ताक्षरित डेटा में न्यूनतम और अधिकतम SDK संस्करण signer के लिए निर्दिष्ट संस्करण से मेल खाते हैं।
    4. सत्यापित करें कि digests और signatures में सिग्नेचर एल्गोरिथम आईडी की ऑर्डर की गई सूची समान है। (यह सिग्नेचर स्ट्रिपिंग/जोड़ को रोकने के लिए है।)
    5. सिग्नेचर एल्गोरिथम द्वारा उपयोग किए गए डाइजेस्ट एल्गोरिथम के समान डाइजेस्ट एल्गोरिथम का उपयोग करके एपीके सामग्री के डाइजेस्ट की गणना करें
    6. सत्यापित करें कि परिकलित डाइजेस्ट digests से संबंधित digest के समान है।
    7. सत्यापित करें कि certificates पत्र के पहले certificate का सब्जेक्टपब्लिककेइन्फो public key के समान है।
    8. यदि signer के लिए प्रूफ-ऑफ-रोटेशन विशेषता मौजूद है, तो सत्यापित करें कि संरचना मान्य है और यह signer सूची में अंतिम प्रमाणपत्र है।
  4. सत्यापन सफल होता है यदि वर्तमान प्लेटफॉर्म की सीमा में एक signer पाया जाता है और चरण 3 उस signer के लिए सफल होता है।

मान्यकरण

यह जांचने के लिए कि आपका डिवाइस v3 को ठीक से सपोर्ट करता है, PkgInstallSignatureVerificationTest.java CTS टेस्ट को cts/hostsidetests/appsecurity/src/android/appsecurity/cts/ में चलाएँ।