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

Android 11, APK सिग्नेचर स्कीम v4 के साथ स्ट्रीमिंग के साथ काम करने वाली साइनिंग स्कीम के साथ काम करता है. v4 सिग्नेचर, APK के सभी बाइट के आधार पर कैलकुलेट किए गए, Merkle हैश ट्री पर आधारित होता है. यह fs-verity हैश ट्री के स्ट्रक्चर का पूरी तरह से पालन करता है. उदाहरण के लिए, साल्ट और आखिरी ब्लॉक को शून्य से पैड करना. Android 11, सिग्नेचर को एक अलग फ़ाइल में सेव करता है. <apk name>.apk.idsigv4 सिग्नेचर के लिए, v2 या v3 सिग्नेचर की ज़रूरत होती है.

फ़ाइल फ़ॉर्मैट

सभी संख्या वाले फ़ील्ड, लिटल इंडियन फ़ॉर्मैट में होते हैं. सभी फ़ील्ड में उतने ही बाइट होते हैं जितने उनके sizeof() में होते हैं. इसमें कोई पैडिंग या अलाइनमेंट नहीं जोड़ा जाता.

परिभाषाओं को आसान बनाने के लिए, यहां एक हेल्पर स्ट्रक्चर दिया गया है.

template <class SizeT>
struct sized_bytes {
        SizeT size;
        byte bytes[size];
};

मुख्य फ़ाइल का कॉन्टेंट:

struct V4Signature {
        int32 version; // only version 2 is supported as of now
        sized_bytes<int32> hashing_info;
        sized_bytes<int32> signing_info;
        sized_bytes<int32> merkle_tree;  // optional
};

hashing_info, हैश ट्री जनरेट करने और रूट हैश के लिए इस्तेमाल किए जाने वाले पैरामीटर हैं:

struct hashing_info.bytes {
    int32 hash_algorithm;    // only 1 == SHA256 supported
    int8 log2_blocksize;     // only 12 (block size 4096) supported now
    sized_bytes<int32> salt; // used exactly as in fs-verity, 32 bytes max
    sized_bytes<int32> raw_root_hash; // salted digest of the first Merkle tree page
};

signing_info यह स्ट्रक्चर है:

struct signing_info.bytes {
    sized_bytes<int32> apk_digest;  // used to match with the corresponding APK
    sized_bytes<int32> x509_certificate; // ASN.1 DER form
    sized_bytes<int32> additional_data; // a free-form binary data blob
    sized_bytes<int32> public_key; // ASN.1 DER, must match the x509_certificate
    int32 signature_algorithm_id; // see the APK v2 doc for the list
    sized_bytes<int32> signature;
};
  • apk_digest को APK के v3 साइनिंग ब्लॉक से लिया जाता है. अगर यह मौजूद नहीं है, तो इसे v2 ब्लॉक से लिया जाता है (apk_digest देखें)

signature कोड बनाने और उसकी पुष्टि करने के लिए, यहां दिए गए डेटा को बाइनरी ब्लॉब में सीरियलाइज़ करना होगा. इसके बाद, उसे हस्ताक्षर करने / पुष्टि करने वाले एल्गोरिदम में, हस्ताक्षर किए गए डेटा के तौर पर पास करना होगा:

struct V4DataForSigning {
        int32 size;
        int64 file_size; // the size of the file that's been hashed.
        hashing_info.hash_algorithm;
        hashing_info.log2_blocksize;
        hashing_info.salt;
        hashing_info.raw_root_hash;
        signing_info.apk_digest;
        signing_info.x509_certificate;
        signing_info.additional_data;
};
  1. merkle_tree, APK का पूरा मेर्कल ट्री है. इसका हिसाब, fs-verity दस्तावेज़ में बताए गए तरीके से लगाया जाता है.

प्रॉड्यूसर और उपभोक्ता

apksigner Android SDK टूल अब डिफ़ॉल्ट पैरामीटर के साथ चलाने पर, v4 सिग्नेचर फ़ाइल जनरेट करता है. v4 साइनिंग को, अन्य साइनिंग स्कीम की तरह ही बंद किया जा सकता है. इससे यह पुष्टि भी की जा सकती है कि v4 हस्ताक्षर मान्य है या नहीं.

adb, adb install --incremental कमांड चलाते समय .apk के बगल में .apk.idsig फ़ाइल मौजूद होने की उम्मीद करता है
यह डिफ़ॉल्ट रूप से इंक्रीमेंटल इंस्टॉलेशन की कोशिश करने के लिए, .idsig फ़ाइल का भी इस्तेमाल करेगा. अगर यह फ़ाइल मौजूद नहीं है या अमान्य है, तो यह सामान्य इंस्टॉलेशन पर वापस आ जाएगा.

जब कोई इंस्टॉलेशन सेशन बनाया जाता है, तो PackageInstaller में मौजूद नया स्ट्रीमिंग इंस्टॉलेशन एपीआई, सेशन में फ़ाइल जोड़ते समय, स्ट्रिप किया गया v4 हस्ताक्षर को अलग आर्ग्युमेंट के तौर पर स्वीकार करता है. इस समय, signing_info को पूरे ब्लॉब के तौर पर incfs में पास किया जाता है. Incfs, ब्लॉब से रूट हैश निकालता है.

इंस्टॉलेशन सेशन को कमिट करते समय, PackageManagerService, incfs से signing_info ब्लॉब को वापस पाने के लिए ioctl करता है. इसके बाद, उसे पार्स करता है और हस्ताक्षर की पुष्टि करता है.

इंक्रीमेंटल डेटा लोडर कॉम्पोनेंट को, डेटा लोडर नेटिव एपीआई के ज़रिए हस्ताक्षर के मेर्कल ट्री वाले हिस्से को स्ट्रीम करना चाहिए.
package सेवा शेल कमांड install-incremental जोड़ी गई हर फ़ाइल के लिए, पैरामीटर के तौर पर, हटाए गए वर्शन 4 के हस्ताक्षर वाली फ़ाइल को base64 के तौर पर एन्कोड करके स्वीकार करता है. उससे जुड़े Merkle tree को कमांड के stdin में भेजना होगा.

apk_digest

apk_digest, कॉन्टेंट डाइजेस्ट का सबसे पहले उपलब्ध क्रम है:

  1. V3, 1 एमबी ब्लॉक, SHA2-512 (CONTENT_DIGEST_CHUNKED_SHA512),
  2. V3, 4KB ब्लॉक, SHA2-256 (CONTENT_DIGEST_VERITY_CHUNKED_SHA256),
  3. V3, 1 एमबी ब्लॉक, SHA2-256 (CONTENT_DIGEST_CHUNKED_SHA256),
  4. V2, SHA2-512,
  5. V2, SHA2-256.

APK सिग्नेचर स्कीम v3 में, लंबाई के पहले वाले सिग्नेचर का लंबाई के पहले वाला क्रम देखें.

apk validation process v4
पहली इमेज: APK की पुष्टि करने की प्रोसेस का चौथा वर्शन

पुष्टि करना और जांच करना

सुविधा की यूनिट टेस्ट और सीटीएस का इस्तेमाल करके, लागू करने की पुष्टि करें.

  • CtsIncrementalInstallHostTestCases
    • /android/cts/hostsidetests/incrementalinstall

हस्ताक्षर के फ़ॉर्मैट की जांच करना

हस्ताक्षर के फ़ॉर्मैट की जांच करने के लिए, डेवलपमेंट एनवायरमेंट सेट अप करें और मैन्युअल तरीके से ये टेस्ट चलाएं:

$ atest PackageManagerShellCommandTest
PackageManagerShellCommandIncrementalTest

Android SDK (ADB और apksigner) की मदद से, हस्ताक्षर के फ़ॉर्मैट की जांच करना

Android SDK टूल की मदद से हस्ताक्षर फ़ॉर्मैट की जांच करने के लिए, डेवलपमेंट एनवायरमेंट सेट अप करें और पक्का करें कि आपने IncFS को लागू कर लिया हो. इसके बाद, टारगेट किए गए फ़िज़िकल डिवाइस या एमुलेटर पर बिल्ड को फ़्लैश करें. आपको एक मौजूदा APK जनरेट करना होगा या उसे हासिल करना होगा. इसके बाद, डीबग साइनिंग पासकोड बनाएं. आखिर में, build-tools फ़ोल्डर से v4 सिग्नेचर फ़ॉर्मैट का इस्तेमाल करके, APK पर हस्ताक्षर करें और उसे इंस्टॉल करें.

साइन करें

$ ./apksigner sign --ks debug.keystore game.apk

इंस्टॉल करें

$ ./adb install game.apk

ये टेस्ट कहां मिल सकते हैं?

/android/cts/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandIncrementalTest.java