एपीके सिग्नेचर स्कीम v2 एक पूरी फाइल सिग्नेचर स्कीम है जो एपीके के संरक्षित हिस्सों में किसी भी बदलाव का पता लगाकर सत्यापन की गति को बढ़ाती है और अखंडता की गारंटी को मजबूत करती है।
एपीके सिग्नेचर स्कीम v2 का उपयोग करके साइन करना ज़िप सेंट्रल डायरेक्टरी सेक्शन से ठीक पहले एपीके फाइल में एपीके साइनिंग ब्लॉक को सम्मिलित करता है। एपीके साइनिंग ब्लॉक के अंदर, v2 हस्ताक्षर और हस्ताक्षरकर्ता पहचान जानकारी एपीके हस्ताक्षर योजना v2 ब्लॉक में संग्रहीत की जाती है।
चित्र 1. हस्ताक्षर करने से पहले और बाद में APK
APK सिग्नेचर स्कीम v2 को Android 7.0 (Nougat) में पेश किया गया था। Android 6.0 (मार्शमैलो) और पुराने उपकरणों पर एपीके को इंस्टॉल करने योग्य बनाने के लिए, v2 योजना के साथ हस्ताक्षर किए जाने से पहले एपीके को JAR साइनिंग का उपयोग करके हस्ताक्षरित किया जाना चाहिए।
APK साइनिंग ब्लॉक
v1 एपीके प्रारूप के साथ पश्च-संगतता बनाए रखने के लिए, v2 और नए एपीके हस्ताक्षर एपीके साइनिंग ब्लॉक के अंदर संग्रहीत किए जाते हैं, एपीके हस्ताक्षर योजना v2 का समर्थन करने के लिए पेश किया गया एक नया कंटेनर। एपीके फ़ाइल में, एपीके साइनिंग ब्लॉक ज़िप केंद्रीय निर्देशिका से ठीक पहले स्थित है, जो फ़ाइल के अंत में स्थित है।
ब्लॉक में आईडी-वैल्यू जोड़े इस तरह से लिपटे होते हैं जिससे एपीके में ब्लॉक का पता लगाना आसान हो जाता है। एपीके का v2 हस्ताक्षर आईडी 0x7109871a आईडी के साथ आईडी-मूल्य जोड़ी के रूप में संग्रहीत किया जाता है।
प्रारूप
एपीके साइनिंग ब्लॉक का प्रारूप इस प्रकार है (सभी संख्यात्मक क्षेत्र छोटे-एंडियन हैं):
- बाइट्स में
size of block
(इस क्षेत्र को छोड़कर) (uint64) - uint64-लंबाई-उपसर्ग आईडी-मान जोड़े का अनुक्रम:
-
ID
(uint32) -
value
(चर-लंबाई: जोड़ी की लंबाई - 4 बाइट्स)
-
- बाइट्स में
size of block
- पहले फ़ील्ड के समान (uint64) -
magic
"एपीके सिग ब्लॉक 42" (16 बाइट्स)
एपीके को पहले ज़िप केंद्रीय निर्देशिका की शुरुआत (फ़ाइल के अंत में केंद्रीय निर्देशिका रिकॉर्ड का ज़िप अंत ढूंढकर, फिर रिकॉर्ड से केंद्रीय निर्देशिका के प्रारंभ ऑफसेट को पढ़कर) को पार्स किया जाता है। magic
मूल्य यह स्थापित करने का एक त्वरित तरीका प्रदान करता है कि केंद्रीय निर्देशिका से पहले एपीके साइनिंग ब्लॉक होने की संभावना है। तब size of block
फ़ाइल में ब्लॉक की शुरुआत को कुशलता से इंगित करता है।
ब्लॉक की व्याख्या करते समय अज्ञात आईडी वाले आईडी-मूल्य जोड़े को अनदेखा किया जाना चाहिए।
APK हस्ताक्षर योजना v2 ब्लॉक
APK पर एक या अधिक हस्ताक्षरकर्ताओं/पहचानों द्वारा हस्ताक्षर किए जाते हैं, प्रत्येक को एक हस्ताक्षर कुंजी द्वारा दर्शाया जाता है। यह जानकारी एपीके सिग्नेचर स्कीम v2 ब्लॉक के रूप में संग्रहीत है। प्रत्येक हस्ताक्षरकर्ता के लिए, निम्नलिखित जानकारी संग्रहीत की जाती है:
- (हस्ताक्षर एल्गोरिथ्म, डाइजेस्ट, सिग्नेचर) टुपल्स। एपीके की सामग्री की अखंडता जांच से हस्ताक्षर सत्यापन को अलग करने के लिए डाइजेस्ट को संग्रहीत किया जाता है।
- X.509 प्रमाणपत्र श्रृंखला हस्ताक्षरकर्ता की पहचान का प्रतिनिधित्व करती है।
- कुंजी-मूल्य जोड़े के रूप में अतिरिक्त विशेषताएँ।
प्रत्येक हस्ताक्षरकर्ता के लिए, एपीके को प्रदान की गई सूची से समर्थित हस्ताक्षर का उपयोग करके सत्यापित किया जाता है। अज्ञात हस्ताक्षर एल्गोरिदम वाले हस्ताक्षरों को अनदेखा कर दिया जाता है। यह प्रत्येक कार्यान्वयन पर निर्भर करता है कि एकाधिक समर्थित हस्ताक्षर मिलने पर किस हस्ताक्षर का उपयोग किया जाए। यह भविष्य में पिछड़े-संगत तरीके से मजबूत हस्ताक्षर विधियों की शुरूआत को सक्षम बनाता है। सुझाया गया तरीका सबसे मजबूत हस्ताक्षर को सत्यापित करना है।
प्रारूप
एपीके सिग्नेचर स्कीम v2 ब्लॉक आईडी 0x7109871a
के तहत एपीके साइनिंग ब्लॉक के अंदर संग्रहीत है।
एपीके सिग्नेचर स्कीम v2 ब्लॉक का प्रारूप इस प्रकार है (सभी संख्यात्मक मान छोटे-एंडियन हैं, सभी लंबाई-उपसर्ग फ़ील्ड लंबाई के लिए uint32 का उपयोग करते हैं):
- लंबाई-उपसर्ग
signer
की लंबाई-उपसर्ग अनुक्रम:- लंबाई-उपसर्ग
signed data
:- लंबाई-प्रीफिक्स्ड
digests
का लंबाई-उपसर्ग अनुक्रम:-
signature algorithm ID
(uint32) - (लंबाई-उपसर्ग)
digest
—अखंडता-संरक्षित सामग्री देखें
-
- X.509
certificates
का लंबाई-उपसर्ग अनुक्रम:- लंबाई-उपसर्ग X.509
certificate
(ASN.1 DER प्रपत्र)
- लंबाई-उपसर्ग X.509
- लंबाई-उपसर्ग
additional attributes
की लंबाई-उपसर्ग अनुक्रम:-
ID
(uint32) -
value
(चर-लंबाई: अतिरिक्त विशेषता की लंबाई - 4 बाइट्स)
-
- लंबाई-प्रीफिक्स्ड
- लंबाई-उपसर्ग
signatures
का लंबाई-उपसर्ग अनुक्रम:-
signature algorithm ID
(uint32) -
signed data
पर लंबाई-उपसर्गsignature
-
- लंबाई-उपसर्ग
public key
(SubjectPublicKeyInfo, ASN.1 DER प्रपत्र)
- लंबाई-उपसर्ग
सिग्नेचर एल्गोरिथम आईडी
- 0x0101—RSASSA-PSS SHA2-256 डाइजेस्ट के साथ, SHA2-256 MGF1, 32 बाइट्स नमक, ट्रेलर: 0xbc
- 0x0102—RSASSA-PSS SHA2-512 डाइजेस्ट के साथ, SHA2-512 MGF1, 64 बाइट्स नमक, ट्रेलर: 0xbc
- 0x0103—RSASSA-PKCS1-v1_5 SHA2-256 डाइजेस्ट के साथ। यह बिल्ड सिस्टम के लिए है जिसके लिए नियतात्मक हस्ताक्षर की आवश्यकता होती है।
- 0x0104—RSASSA-PKCS1-v1_5 SHA2-512 डाइजेस्ट के साथ। यह बिल्ड सिस्टम के लिए है जिसके लिए नियतात्मक हस्ताक्षर की आवश्यकता होती है।
- 0x0201—ईसीडीएसए SHA2-256 डाइजेस्ट के साथ
- 0x0202—ईसीडीएसए SHA2-512 डाइजेस्ट के साथ
- 0x0301—SHA2-256 डाइजेस्ट के साथ DSA
उपरोक्त सभी हस्ताक्षर एल्गोरिदम एंड्रॉइड प्लेटफॉर्म द्वारा समर्थित हैं। हस्ताक्षर उपकरण एल्गोरिदम के सबसेट का समर्थन कर सकते हैं।
समर्थित कुंजी आकार और ईसी वक्र:
- आरएसए: 1024, 2048, 4096, 8192, 16384
- ईसी: एनआईएसटी पी-256, पी-384, पी-521
- डीएसए: 1024, 2048, 3072
अखंडता-संरक्षित सामग्री
एपीके सामग्री की सुरक्षा के उद्देश्य से, एपीके में चार खंड होते हैं:
- ज़िप प्रविष्टियों की सामग्री (ऑफसेट 0 से एपीके साइनिंग ब्लॉक की शुरुआत तक)
- APK साइनिंग ब्लॉक
- ज़िप केंद्रीय निर्देशिका
- केंद्रीय निर्देशिका का ज़िप अंत
चित्रा 2. एपीके अनुभाग हस्ताक्षर करने के बाद
एपीके सिग्नेचर स्कीम v2 सेक्शन 1, 3, 4 और सेक्शन 2 के अंदर निहित एपीके सिग्नेचर स्कीम v2 ब्लॉक के signed data
ब्लॉक की अखंडता की रक्षा करता है।
खंड 1, 3, और 4 की अखंडता को signed data
ब्लॉकों में संग्रहीत उनकी सामग्री के एक या अधिक डाइजेस्ट द्वारा संरक्षित किया जाता है, जो बदले में, एक या अधिक हस्ताक्षरों द्वारा संरक्षित होते हैं।
खंड 1, 3, और 4 में डाइजेस्ट की गणना इस प्रकार की जाती है, जो दो-स्तरीय मर्कल ट्री के समान है। प्रत्येक अनुभाग को लगातार 1 एमबी (2 20 बाइट्स) भागों में विभाजित किया गया है। प्रत्येक खंड में अंतिम हिस्सा छोटा हो सकता है। प्रत्येक चंक के डाइजेस्ट की गणना बाइट 0xa5
के संयोजन, बाइट्स में चंक की लंबाई (छोटे-एंडियन uint32), और चंक की सामग्री पर की जाती है। शीर्ष-स्तरीय डाइजेस्ट की गणना बाइट 0x5a
के संयोजन, विखंडू की संख्या (छोटे-एंडियन uint32) पर की जाती है, और एपीके में विखंडू के प्रकट होने के क्रम में विखंडू के डाइजेस्ट के संयोजन की गणना की जाती है। डाइजेस्ट की गणना खंडित तरीके से की जाती है ताकि गणना को समानांतर करके गति प्रदान की जा सके।
चित्र 3. एपीके डाइजेस्ट
अनुभाग 4 (केंद्रीय निर्देशिका का ज़िप अंत) का संरक्षण ज़िप केंद्रीय निर्देशिका के ऑफसेट वाले अनुभाग द्वारा जटिल है। जब एपीके साइनिंग ब्लॉक का आकार बदलता है, उदाहरण के लिए, जब एक नया हस्ताक्षर जोड़ा जाता है, तो ऑफसेट बदल जाता है। इस प्रकार, केंद्रीय निर्देशिका के ज़िप अंत पर डाइजेस्ट की गणना करते समय, ज़िप केंद्रीय निर्देशिका के ऑफ़सेट वाले फ़ील्ड को एपीके साइनिंग ब्लॉक के ऑफ़सेट के रूप में माना जाना चाहिए।
रोलबैक सुरक्षा
एक हमलावर एंड्रॉइड प्लेटफॉर्म पर v2-हस्ताक्षरित एपीके को v1-हस्ताक्षरित एपीके के रूप में सत्यापित करने का प्रयास कर सकता है जो v2-हस्ताक्षरित एपीके को सत्यापित करने का समर्थन करता है। इस हमले को कम करने के लिए, v2-हस्ताक्षरित APK जो कि v1-हस्ताक्षरित भी हैं, उनकी META-INF/*.SF फ़ाइलों के मुख्य भाग में एक X-Android-APK-Signed विशेषता होनी चाहिए। विशेषता का मान एपीके हस्ताक्षर योजना आईडी का अल्पविराम से अलग किया गया सेट है (इस योजना की आईडी 2 है)। v1 हस्ताक्षर को सत्यापित करते समय, APK सत्यापनकर्ता को उन APK को अस्वीकार करने की आवश्यकता होती है जिनके पास APK हस्ताक्षर योजना के लिए हस्ताक्षर नहीं है, सत्यापनकर्ता इस सेट से पसंद करता है (उदाहरण के लिए, v2 योजना)। यह सुरक्षा इस तथ्य पर निर्भर करती है कि सामग्री META-INF/*.SF फ़ाइलें v1 हस्ताक्षरों द्वारा सुरक्षित हैं। JAR हस्ताक्षरित APK सत्यापन पर अनुभाग देखें।
एक हमलावर एपीके सिग्नेचर स्कीम v2 ब्लॉक से मजबूत हस्ताक्षर छीनने का प्रयास कर सकता है। इस हमले को कम करने के लिए, हस्ताक्षर एल्गोरिदम आईडी की सूची जिसके साथ एपीके पर हस्ताक्षर किए जा रहे थे, signed data
ब्लॉक में संग्रहीत किया जाता है जो प्रत्येक हस्ताक्षर द्वारा संरक्षित होता है।
सत्यापन
Android 7.0 और बाद के संस्करणों में, APK को APK सिग्नेचर स्कीम v2+ या JAR साइनिंग (v1 स्कीम) के अनुसार सत्यापित किया जा सकता है। पुराने प्लेटफ़ॉर्म v2 हस्ताक्षरों को अनदेखा करते हैं और केवल v1 हस्ताक्षर सत्यापित करते हैं।
चित्र 4. APK हस्ताक्षर सत्यापन प्रक्रिया (लाल रंग में नए चरण)
APK हस्ताक्षर योजना v2 सत्यापन
- एपीके साइनिंग ब्लॉक का पता लगाएँ और सत्यापित करें कि:
- एपीके साइनिंग ब्लॉक के दो आकार के क्षेत्रों में एक ही मूल्य होता है।
- ज़िप सेंट्रल डायरेक्टरी के तुरंत बाद सेंट्रल डायरेक्ट्री रिकॉर्ड का ज़िप एंड होता है।
- केंद्रीय निर्देशिका के ज़िप अंत का अधिक डेटा द्वारा अनुसरण नहीं किया जाता है।
- एपीके साइनिंग ब्लॉक के अंदर पहले एपीके सिग्नेचर स्कीम v2 ब्लॉक का पता लगाएँ। यदि v2 ब्लॉक मौजूद है, तो चरण 3 पर आगे बढ़ें। अन्यथा, v1 योजना का उपयोग करके एपीके को सत्यापित करने के लिए वापस आएं।
- एपीके सिग्नेचर स्कीम v2 ब्लॉक में प्रत्येक
signer
के लिए:- सिग्नेचर से सबसे मजबूत समर्थित
signatures
signature algorithm ID
चुनें। स्ट्रेंथ ऑर्डरिंग प्रत्येक कार्यान्वयन/प्लेटफ़ॉर्म संस्करण पर निर्भर है। -
public key
का उपयोग करकेsigned data
के विरुद्धsignatures
से संबंधितsignature
सत्यापित करें। (अबsigned data
को पार्स करना सुरक्षित है।) - सत्यापित करें कि
digests
औरsignatures
में सिग्नेचर एल्गोरिथम आईडी की ऑर्डर की गई सूची समान है। (यह सिग्नेचर स्ट्रिपिंग/जोड़ को रोकने के लिए है।) - सिग्नेचर एल्गोरिथम द्वारा उपयोग किए गए डाइजेस्ट एल्गोरिथम के समान डाइजेस्ट एल्गोरिथम का उपयोग करके एपीके सामग्री के डाइजेस्ट की गणना करें ।
- सत्यापित करें कि परिकलित डाइजेस्ट
digests
से संबंधितdigest
के समान है। - सत्यापित करें कि
certificates
पत्र के पहलेcertificate
का सब्जेक्टपब्लिककेइन्फोpublic key
के समान है।
- सिग्नेचर से सबसे मजबूत समर्थित
- सत्यापन सफल होता है यदि कम से कम एक
signer
पाया जाता है और प्रत्येक पाए गएsigner
के लिए चरण 3 सफल होता है।
नोट : यदि चरण 3 या 4 में कोई विफलता होती है, तो APK को v1 योजना का उपयोग करके सत्यापित नहीं किया जाना चाहिए।
JAR-हस्ताक्षरित APK सत्यापन (v1 योजना)
JAR-हस्ताक्षरित APK एक मानक हस्ताक्षरित JAR है, जिसमें ठीक META-INF/MANIFEST.MF में सूचीबद्ध प्रविष्टियाँ होनी चाहिए और जहाँ सभी प्रविष्टियों पर हस्ताक्षरकर्ताओं के एक ही समूह द्वारा हस्ताक्षर किए जाने चाहिए। इसकी अखंडता की पुष्टि निम्नानुसार की जाती है:
- प्रत्येक हस्ताक्षरकर्ता को META-INF/<signer>.SF और META-INF/<signer>.(RSA|DSA|EC) JAR प्रविष्टि द्वारा दर्शाया जाता है।
- <हस्ताक्षरकर्ता>.(RSA|DSA|EC) एक PKCS #7 CMS ContentInfo है, जिसमें SignedData संरचना होती है , जिसके हस्ताक्षर <signer>.SF फ़ाइल पर सत्यापित होते हैं।
- <हस्ताक्षर>.SF फ़ाइल में META-INF/MANIFEST.MF का संपूर्ण फ़ाइल डाइजेस्ट होता है और META-INF/MANIFEST.MF के प्रत्येक अनुभाग का डाइजेस्ट होता है। MANIFEST.MF की संपूर्ण-फ़ाइल डाइजेस्ट सत्यापित है। यदि वह विफल हो जाता है, तो इसके बजाय प्रत्येक MANIFEST.MF अनुभाग का डाइजेस्ट सत्यापित किया जाता है।
- META-INF/MANIFEST.MF में, प्रत्येक अखंडता-संरक्षित JAR प्रविष्टि के लिए, प्रविष्टि की असम्पीडित सामग्री के डाइजेस्ट युक्त एक संगत नामित अनुभाग होता है। ये सभी पाचन सत्यापित हैं।
- एपीके सत्यापन विफल हो जाता है यदि एपीके में जेएआर प्रविष्टियां हैं जो MANIFEST.MF में सूचीबद्ध नहीं हैं और जेएआर हस्ताक्षर का हिस्सा नहीं हैं।
सुरक्षा श्रृंखला इस प्रकार है <हस्ताक्षर>। (आरएसए | डीएसए | ईसी) -> <हस्ताक्षर>। एसएफ -> MANIFEST.MF -> प्रत्येक अखंडता-संरक्षित JAR प्रविष्टि की सामग्री।