APK Signature Scheme v2(二)

背景

在Android7.0剛剛出來的時候寫了一篇關于新的簽名方式簡單介紹Android 7.0新簽名方式 V2,有需要了解的朋友也可以去簡單了解一下。也是這篇文章,有讀者看了之后,希望我深入的講解一下,正好自己最近也看一些資料:
新簽名方式多渠道打包

區別

大家可以看到:
新的簽名方案會在ZIP文件格式的 Central Directory 區塊所在文件位置的前面添加一個APK Signing Block區塊,下面按照ZIP文件的格式來分析新應用簽名方案簽名后的APK包。

整個APK(ZIP文件格式)會被分為以下四個區塊:

  1. Contents of ZIP entries(from offset 0 until the start of APK Signing Block)
  2. APK Signing Block
  3. ZIP Central Directory
  4. ZIP End of Central Directory

其中:
應用簽名方案的簽名信息會被保存在區塊2(APK Signing Block)中, 而區塊1(Contents of ZIP entries)、區塊3(ZIP Central Directory)、區塊4(ZIP End of Central Directory)是受保護的,在簽名后任何對區塊1、3、4的修改都逃不過新的應用簽名方案的檢查。

簽名區域

通過上面的描述,可以看出因為APK包的區塊1、3、4都是受保護的,任何修改在簽名后對它們的修改,都會在安裝過程中被簽名校驗檢測失敗,而區塊2(APK Signing Block)是不受簽名校驗規則保護的,那是否可以在這個不受簽名保護的區塊2(APK Signing Block)上做文章呢?我們先來看看對區塊2格式的描述:

偏移 字節數 描述
@+0 8 這個Block的長度(本字段的長度不計算在內)
@+8 n 一組ID-value
@-24 8 這個Block的長度(和第一個字段一樣值)
@-16 16 魔數 “APK Sig Block 42”
區塊2中APK Signing Block是由這幾部分組成:2個用來標示這個區塊長度的8字節 + 這個區塊的魔數(APK Sig Block 42)+ 這個區塊所承載的數據(ID-value)。

我們重點來看一下這個ID-value,它由一個8字節的長度標示+4字節的ID+它的負載組成。V2的簽名信息是以ID(0x7109871a)的ID-value來保存在這個區塊中,不知大家有沒有注意這是一組ID-value,也就是說它是可以有若干個這樣的ID-value來組成。

解析

我們來看看其中的執行方式:


public static ByteBuffer findApkSignatureSchemeV2Block(
            ByteBuffer apkSigningBlock,
            Result result) throws SignatureNotFoundException {
        checkByteOrderLittleEndian(apkSigningBlock);
        // FORMAT:
        // OFFSET       DATA TYPE  DESCRIPTION
        // * @+0  bytes uint64:    size in bytes (excluding this field)
        // * @+8  bytes pairs
        // * @-24 bytes uint64:    size in bytes (same as the one above)
        // * @-16 bytes uint128:   magic
        ByteBuffer pairs = sliceFromTo(apkSigningBlock, 8, apkSigningBlock.capacity() - 24);

        int entryCount = 0;
        while (pairs.hasRemaining()) {
            entryCount++;
            if (pairs.remaining() < 8) {
                throw new SignatureNotFoundException(
                        "Insufficient data to read size of APK Signing Block entry #" + entryCount);
            }
            long lenLong = pairs.getLong();
            if ((lenLong < 4) || (lenLong > Integer.MAX_VALUE)) {
                throw new SignatureNotFoundException(
                        "APK Signing Block entry #" + entryCount
                                + " size out of range: " + lenLong);
            }
            int len = (int) lenLong;
            int nextEntryPos = pairs.position() + len;
            if (len > pairs.remaining()) {
                throw new SignatureNotFoundException(
                        "APK Signing Block entry #" + entryCount + " size out of range: " + len
                                + ", available: " + pairs.remaining());
            }
            int id = pairs.getInt();
            if (id == APK_SIGNATURE_SCHEME_V2_BLOCK_ID) {
                return getByteBuffer(pairs, len - 4);
            }
            result.addWarning(Issue.APK_SIG_BLOCK_UNKNOWN_ENTRY_ID, id);
            pairs.position(nextEntryPos);
        }

        throw new SignatureNotFoundException(
                "No APK Signature Scheme v2 block in APK Signing Block");
    }

其中最重要的是:

if (id == APK_SIGNATURE_SCHEME_V2_BLOCK_ID) 

通過源代碼可以看出Android是通過查找ID為 APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a 的ID-value,來獲取APK Signature Scheme v2 Block,對這個區塊中其他的ID-value選擇了忽略。

總結

上面是大致的V2簽名的信息,主要是參考了美團的文章,感謝大神們的分享,后面再給大家分享一篇關于新的簽名方式下的多渠道快速打包

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容