安卓簽名校驗機制

Joooook發表於2024-09-15

安卓簽名校驗機制

目錄

  • 1 V1方案
    • 1.1 V1方案的安全性
  • 2 V2方案
    • 2.1 摘要計算過程
    • 2.2 防回滾繞過
  • 3 V3方案
  • 4 V4方案
  • 5 簽名實踐
    • 5.1 keytool生成金鑰庫
    • 5.2 jarsigner
    • 5.3 apksigner
  • 6 引用

安卓的簽名校驗機制共有三代。

9.0以上的系統會判斷apk是否使用到V3版本的簽名,如果有,那麼按照V3版本簽名校驗方式進行校驗校驗成功直接安裝,校驗失敗拒絕安裝;如果apk不是使用V3簽名,判斷是不是使用V2,如果沒有使用V2那麼再判斷是不是使用V1的簽名。

1 V1方案

v1簽名後會增加META-INF資料夾,其中會有如下三個檔案:

  • MANIFEST.MF:儲存apk中每一個檔案的摘要。
  • *.SFMANIFEST.MF 檔案的摘要資訊以及 MANIFEST.MF 檔案當中每個條目在用摘要演算法計算得到的摘要資訊。
  • *.RSA:包含*.SF的簽名及簽名的公鑰證書

以小米萬能遙控的包apk為例

META-INF資料夾

MANIFEST.MF儲存了檔名及其SHA256摘要的base64編碼

*.SFMANIFEST.MF多了MANIFEST.MF的摘要,並且對MANIFEST.MF中的每個模組都進行了摘要。

如何區別一個模組,檢視檔案的十六進位制,一個模組是以0D0A0D0A結尾的,其實就是兩次換行。

AndroidManifest.xml模組來驗證

*.RSAPKCS#7格式的資料經過ASN.1 DER規則編碼之後的二進位制檔案

使用以下命令列讀取

openssl pkcs7 -inform DER -in <*.RSA檔案路徑> -text -noout -print_certs

1.1 V1方案的安全性

APK 包的完整性校驗不夠強。如果我們在 APK 簽名後,對 APK 包中沒有涉及到原始檔案的資料塊做改變,那麼這層校驗機制就會失效。

2 V2方案

APK 簽名方案 v2 是一種全檔案簽名方案,該方案能夠發現對 APK 受保護部分進行的所有更改

APK Signing Bolck 由這幾個部分組成:

偏移 位元組數 描述
@0 8 這個 Block 的長度(本欄位的長度不計算在內)
@8 n 一組 ID-value
@-24 8 這個 Bolck 的長度(和第一個欄位一樣值)
@-16 16 魔數 "APK Sig Block 42"

具體結構如下

ID = 0x7109871a的鍵值對塊就是儲存V2簽名資訊的地方。開頭示例如下

結尾處示例

美團團隊透過自定義ID,可以用來生成渠道包https://tech.meituan.com/2017/01/13/android-apk-v2-signature-scheme.html

ID = 0x7109871a的鍵值對塊中的Value儲存的是v2簽名資訊。

其中可以儲存了一份或者多份APK簽名資訊(多個簽名者)。

Value的內容結果如下

具體如下

示例分析。紅框部分為摘要,紫框部分為證書。

2.1 摘要計算過程

摘要計算只針對原始zip內容

  • 拆分塊chunk

    將每個部分(即上面標註第1、3、4部分)拆分成多個大小為 1 MB大小的塊chunk,最後一個塊chunk可能小於1MB。之所以分塊,是為了可以透過平行計算摘要以加快計算速度

  • 計算塊chunk摘要

    0xa5 + chunk長度(位元組數) + chunk內容 拼接起來用對應的摘要演算法進行計算出每一塊的摘要值;

  • 計算整體摘要

    0x5a + chunk數 + chunk摘要(按塊在 APK 中的順序)拼接起來用對應的摘要演算法進行計算出整體的摘要值

2.2 防回滾繞過

為了防止攻擊者刪除apk中的v2方案從而繞過,帶 v2 簽名的 APK如果還帶 V1 簽名,其 META-INF/*.SF 檔案的主要部分中必須包含 X-Android-APK-Signed 屬性。

3 V3方案

APK 的 v3 簽名儲存為 ID 值對,ID 為 0xf05368c0。v3 方案的設計與v2 方案非常相似。它具有相同的通用格式,新增了有關支援的SDK版本和proof-of-rotation結構的資訊。

簡單來說APK v3就是為了Andorid9的APK 金鑰輪替功能而出現的,就是在v2的基礎上增加兩個資料塊來儲存APK 金鑰輪替(更新簽名金鑰)所需要的一些資訊,所以可以看成是v2的升級。具體結構見官網說明即可。

4 V4方案

APK v4是為了ADB 增量 APK 安裝出現的

增量更新是基於 BSDiff 這個差量更新演算法,基於兩個 apk 位元組碼的差異,在服務端生成 patch 包,然後客戶端透過同樣的演算法,把已安裝的 apk 與 patch 包結合生成更新後的apk進行安裝,以此減小 app 版本升級時的下載時間,提高更新效率。

簽名方式和v2v3有所不同。

5 簽名實踐

以下介紹jarsignerapksigner簽名工具的使用。

  • jarsignerJDK提供的針對jar包簽名的通用工具,位置在JDK/bin/jarsigner
  • apksigner是Google官方提供的針對Android apk簽名及驗證的專用工具,位置在Android SDK/build-tools/SDK版本/apksigner

但這兩種工具的簽名都要使用到金鑰庫檔案,所以順便介紹金鑰庫生成。

5.1 keytool生成金鑰庫

使用keytool生成金鑰庫

keytool -genkey -keyalg RSA -keystore (指定金鑰庫檔名) demo.keystore

填寫資訊即可生成,

這個條目名字也是要用到的

或者我們可以指定條目名字

keytool -genkey -keyalg RSA -keystore demo1.keystore -alias test

5.2 jarsigner

簽名命令

jarsigner -keystore 金鑰庫名 xxx.apk 金鑰別名

還有以下兩個引數比較重要

  • -digestalg 摘要演算法
  • -sigalg 簽名演算法

5.3 apksigner

apksigner sign --ks demo1.keystore --ks-key-alias test app-debug.apk

apksigner預設開啟v1v2簽名,可以用以下引數關閉。

  • --v1-signing-enabled false
  • --v2-signing-enabled false

6 引用

Android V2簽名與校驗原理分析-CSDN

簽名校驗機制.md-Github

AndroidV1,V2,V3簽名原理詳解-騰訊雲開發者社群-騰訊雲

Android apk之v1、v2、v3簽名-知乎

Android V2簽名與校驗原理分析_v2 方案校驗不透過-CSDN部落格

Android中APK簽名工具之jarsigner和apksigner詳解-CSDN部落格

相關文章