安卓簽名校驗機制
目錄
- 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中每一個檔案的摘要。*.SF
:MANIFEST.MF
檔案的摘要資訊以及MANIFEST.MF
檔案當中每個條目在用摘要演算法計算得到的摘要資訊。*.RSA
:包含*.SF
的簽名及簽名的公鑰證書
以小米萬能遙控的包apk
為例
META-INF
資料夾
MANIFEST.MF
儲存了檔名及其SHA256
摘要的base64
編碼
*.SF
比MANIFEST.MF
多了MANIFEST.MF
的摘要,並且對MANIFEST.MF
中的每個模組都進行了摘要。
如何區別一個模組,檢視檔案的十六進位制,一個模組是以0D0A0D0A
結尾的,其實就是兩次換行。
取AndroidManifest.xml
模組來驗證
*.RSA
是PKCS#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 簽名實踐
以下介紹jarsigner
和apksigner
簽名工具的使用。
jarsigner
是JDK
提供的針對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
預設開啟v1
和v2
簽名,可以用以下引數關閉。
--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部落格