Android | 他山之石,可以攻玉誉裆!一篇文章看懂 v1/v2/v3 簽名機制

點贊關注顿颅,不再迷路,你的支持對我意義重大足丢!

?? Hi粱腻,我是丑丑。本文 GitHub · Android-NoteBook 已收錄斩跌,這里有 Android 進階成長路線筆記 & 博客绍些,歡迎跟著彭丑丑一起成長。(聯(lián)系方式 & 入群方式在 GitHub)

前言

  • 在打生產包時耀鸦,一定需要對 apk 簽名柬批,那么你知道為什么要給應用簽名嗎?
  • 在這篇文章里袖订,我將分析 Android apk 的簽名機制氮帐,并介紹 v1、v2 和 v3 三種安裝包簽名方案的原理與演進洛姑。如果能幫上忙上沐,請務必點贊加關注,這真的對我非常重要楞艾。

目錄


前置知識

這篇文章的內容會涉及以下前置 / 相關知識参咙,貼心的我都幫你準備好了龄广,請享用~


1. 什么是應用簽名净宵?

1.1 數(shù)字簽名模型

數(shù)字簽名(Digital Signature)也叫作數(shù)字指紋(Digital Fingerprint)敲才,它是消息摘要算法和非對稱加密算法的結合體,能夠驗證數(shù)據的完整性塘娶,并且認證數(shù)據的來源归斤。

數(shù)據簽名算法的模型分為兩個主要階段:

  • 1痊夭、簽名: 先計算數(shù)據的 [摘要]刁岸,再使用私鑰對 [摘要] 進行加密生成 [簽名],將 [數(shù)據 + 簽名] 一并發(fā)送給接收方她我;
  • 2虹曙、驗證: 先使用相同的摘要算法計算接收數(shù)據的 [摘要],再使用預先得到的公鑰解密 [簽名]番舆,對比 [解密的簽名] 和 [計算的摘要] 是否一致酝碳。若一致,則說明數(shù)據沒有被篡改恨狈。

需要注意的是疏哗,Android 目前不對應用證書進行 CA 認證,應用可以由第三方(OEM禾怠、運營商返奉、其他應用市場)簽名,也可以自行簽名吗氏。

1.2 為什么要給應用簽名芽偏?

應用 APK 其實是一種特殊的 Zip 壓縮包,無法避免惡意破解者解壓 / 反編譯修改內容弦讽,針對這個問題有何解決方案呢污尉?他山之石,可以攻玉 ——數(shù)字簽名算法往产。應用簽名正是數(shù)字簽名算法的應用場景之一被碗,與其他應用場景類似,目的無非是:

  • 認證

Android 平臺上運行的每個應用都必須有開發(fā)者的簽名仿村。在安裝應用時锐朴,軟件包管理器會驗證 APK 是否已經過適當簽名,安裝程序會拒絕沒有獲得簽名就嘗試安裝的應用奠宜。

  • 驗證完整性

軟件包管理器在安裝應用前會驗證應用摘要包颁,如果破解者修改了 apk 里的內容瞻想,那么摘要就不再匹配,驗證失斆浣馈(驗證流程見下文方案)蘑险。

提示: 使用數(shù)字簽名的優(yōu)點是驗證過程無須復雜的接口和權限,只需要在本機驗證岳悟。

1.3 應用簽名方案演進

截止至 Android 11佃迄,Android 支持以下三種應用簽名方案:

  • v1 簽名方案:基于 Jar 簽名;
  • v2 簽名方案:提高驗證速度和覆蓋度(在 Android 7.0 Nougat 中引入)贵少;
  • v3 簽名方案:實現(xiàn)密鑰輪轉(在 Android 9.0 Pie 中引入)呵俏。

為了提高兼容性,必須按照 v1滔灶、v2普碎、v3 的先后順序采用簽名方案,低版本平臺會忽略高版本的簽名方案在 APK 中添加的額外數(shù)據录平。

引用自 https://source.android.com/security/apksigning/v2 —— Android Developers

2. 簽名方案 v1

v1 簽名方案是基于 Jar 的簽名麻车。

2.1 簽名產物

首先,我們先來分析其簽名產物斗这。v1 簽名后會增加 META-INF 文件夾动猬,其中會有如下三個文件”砑考慮到使用不同的證書和簽名方式赁咙,得到的文件名可能不同,因此你只要留意文件的后綴即可:

META-INF
├── MANIFEST.MF
├── CERT.SF
├── CERT.RSA
文件 描述
MANIFEST.MF 記錄「apk 中每一個文件對應的摘要」(除了 META-INF 文件夾)
*.SF 記錄「MANIFEST.MF 文件的摘要」和「MANIFEST.MF 中每個數(shù)據塊的摘要」
*.RSA 包含了「*.SF 文件的簽名」和「包含公鑰的開發(fā)者證書」

提示: 如果 apk 中文件數(shù)很多免钻,而且文件名很長彼水,那么 MANIFEST.MF*.SF 兩個文件會變得很大。有沒有辦法優(yōu)化呢伯襟?見 第 5.1 節(jié) 優(yōu)化摘要記錄文件大小猿涨。

2.2 簽名流程

v1 簽名流程如下:

  • 1、計算每個文件的 SHA-1 摘要姆怪,進行 BASE64 編碼后寫入 MANIFEST.MF 文件叛赚;

MANIFEST.MF(Message Digest File,摘要文件)

Manifest-Version: 1.0
Built-By: Generated-by-ADT
Created-By: Android Gradle 3.1.0

Name: AndroidManifest.xml
SHA1-Digest: 9hTSmRfzHEeQc7V2wxBbTT3DmCY= 【文件的摘要】

...
  • 2稽揭、計算整個 MANIFEST.MF 文件的 SHA-1 摘要俺附,進行 BASE64 編碼后寫入 *.SF 文件;
  • 3溪掀、計算 MANIFEST.MF 文件中每一塊摘要的 SHA-1 摘要事镣,進行 BASE64 編碼后寫入 *.SF 文件;

\*.SF(Signature File揪胃,簽名文件)

Signature-Version: 1.0
Created-By: 1.0 (Android)
SHA1-Digest-Manifest: MJQyZ0dc4dv7G9nlJPAMQLwEwbU= 【MANIFEST.MF 文件的摘要】
X-Android-APK-Signed: 2

Name: AndroidManifest.xml
SHA1-Digest: IJioMmfD693T4qnUJcPKhq9woHQ= 【摘要的摘要】

...
  • 4璃哟、計算整個 *.SF 文件的數(shù)字簽名(先摘要再私鑰加密)氛琢;
  • 5、將數(shù)字簽名和 X.509 開發(fā)者數(shù)字證書(公鑰)寫入 *.RSA 文件随闪。

提示:*.RSA 文件加密了阳似,需要使用 openssl 工具打開。

引用自 https://zhuanlan.zhihu.com/p/108034286 —— 木質的旋律 著

2.3 驗證流程

驗證流程可以分為驗證簽名和驗證完整性兩個步驟:

驗證簽名步驟:

  • 1铐伴、取出 *.RSA 中包含的開發(fā)者證書撮奏;
  • 2、【注意:這里不向 CA 認證開發(fā)者證書合法性】当宴;
  • 3畜吊、用證書中的公鑰解密 *.RSA 中包含的簽名,得到摘要户矢;
  • 4玲献、計算 *.SF 的摘要;
  • 5逗嫡、對比 (3) 和 (4) 的摘要是否一致青自;

如果上述簽名驗證結果正確株依,才會驗證完整性:

  • 1驱证、計算 MANIFEST.MF 的摘要;
  • 2恋腕、對比 *.SF 記錄中的文件摘要和 (1) 的摘要是否一致抹锄;
  • 3、如果一致荠藤,再用 MANIFEST.MF 中的每一塊數(shù)據去校驗每一個文件是否被修改伙单。

以上任何步驟驗證失敗,則整個 APK 驗證失敗哈肖。

2.4 存在的問題

  • 完整性覆蓋范圍不足:Zip 文件中部分內容不在驗證范圍吻育,例如 META-INF 文件夾;
  • 驗證速度較差:驗證程序必須解壓所有壓縮的條目淤井,這需要花費更多時間和內存布疼。

為了解決這些問題,Android 7.0 中引入了 APK 簽名方案 v2币狠。


3. 簽名方案 v2

v2 簽名方案是一種 全文件簽名方案游两,該方案能夠發(fā)現(xiàn)對 APK 的受保護部分進行的所有更改,相對于 v1 簽名方案驗證速度更快漩绵,完整性覆蓋范圍更廣贱案。

提示: 為了兼容低版本,使用 v2 簽名方案的同時止吐,還需要使用 v1 簽名方案宝踪。

3.1 Zip 文件簡介

在分析 v2 簽名方案之前侨糟,我們先簡單了解一下 Zip 文件格式:

  • Zip 文件主體結構分為三個部分:「條目內容區(qū)」&「中央目錄區(qū)」&「中央目錄結尾區(qū)(EoCD)」

  • EoCD 中記錄了中央目錄的起始位置瘩燥,在「條目內容區(qū)」和「中央目錄區(qū)」之間插入了其他數(shù)據不會影響 Zip 解壓粟害。

3.2 簽名產物

首先,我們先來分析其簽名產物颤芬。v2 簽名后會在 「條目內容區(qū)」和「中央目錄區(qū)」之間插入「APK 簽名分塊(APK Signing Block)」悲幅。

引用自 https://source.android.com/security/apksigning/v2 —— Android Developers

從左到右邊,我們定義為區(qū)塊 1~4站蝠。

3.2 簽名流程

相對與 v1 簽名方案汰具,v2 簽名方案不再以文件為單位計算摘要了,而是以 1 MB 為單位將文件拆分為多個連續(xù)的塊(chunk)菱魔,每個分區(qū)的最后一個塊可能會小于 1 MB留荔。

v2 簽名流程如下:

  • 1、對區(qū)塊 1澜倦、3聚蝶、4,按照 1MB 大小分割為多個塊(chunk)藻治;
  • 2碘勉、計算每個塊的摘要;
  • 3桩卵、計算 (2) 中所有摘要的簽名验靡。
  • 4、添加 X.509 開發(fā)者數(shù)字證書(公鑰)
引用自 https://source.android.com/security/apksigning/v2 —— Android Developers

3.3 驗證流程

驗證流程可以分為驗證簽名和驗證完整性兩個步驟:

  • 驗證簽名步驟:用公鑰驗證區(qū)塊 2 的簽名雏节;
  • 驗證完整性步驟:用「APK數(shù)據摘要集」驗證每一塊數(shù)據的摘要胜嗓。

4. 簽名方案 v3

簽名方案 v3 支持密鑰輪換,應用能夠在 APK 更新過程中更改其簽名密鑰钩乍。

【累了辞州,后面先不寫了...】


5. 衍生應用場景

這一節(jié),我們介紹基于 Android 應用簽名機制的衍生應用場景寥粹。

5.1 優(yōu)化摘要記錄文件大小

在 v1 方案中变过,MANIFEST.MF*.SF 這兩個文件會記錄大量的文件名和文件摘要。如果 apk 中文件數(shù)很多排作,而且文件名很長牵啦,那么這兩個文件會變得很大。使用 AndResGuard 工具妄痪,可以將文件名轉換為短路徑文件名哈雏,從而減少這兩個文件的大小。

引用自 https://time.geekbang.org/column/article/81483 —— 張紹文 著

5.2 多渠道打包方案

在實際生產中,往往需要生成多個渠道的 APK 包裳瘪,傳統(tǒng)的方法是使用 APKTool 逆向工具土浸、Flavor + BuildType 等方案,這一類多渠道打包方案的缺點是耗時嚴重彭羹。隨著 Android 應用簽名方案的演進黄伊,演變出了不同的多渠道打包方案:

v1 方案時代下的多渠道打包

  • 添加空文件

在 v1 方案中,我們提到了完整性校驗不覆蓋到 META-INF 文件夾的問題派殷。有些多渠道打包方案就是利用了這個問題还最,在 META-INF 文件夾下添加空文件,用空文件的名稱來作為渠道的唯一標識毡惜,就可以節(jié)省打包的時間拓轻,提高打渠道包的速度。

  • Zip Comment

除了添加空文件的方法经伙,還可以向 APK 添加 Zip Comment 來生成多渠道包(APK 本身就是特殊的 Zip 包)扶叉。

v2 方案時代下的多渠道打包

在 v2 簽名方案中,幾乎整個 APK 都納入保護范圍帕膜,如果向 APK 添加空文件或 Zip Comment 的話枣氧,在安裝時會報以下錯誤:

Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: 
Failed to collect certificates from base.apk: META-INF/CERT.SF indicates base.apk is signed using APK Signature Scheme v2, 
but no such signature was found. Signature stripped?]

新背景下的多渠道打包方案,則是利用了 APK 簽名分塊(區(qū)塊 2)不受保護 & 字段可擴展的特點垮刹,向區(qū)塊中添加多渠道信息(ID-Value)达吞,例如 美團多渠道打包方案 Walle


6. 總結

  • 簽名應用是處于兩個目的:認證 & 驗證完整性危纫,即:認證 APK 的開發(fā)者以及驗證 APK 內容是否被篡改宗挥。截止到 Android 11,一共有 v1种蝶、v2、v3 三種簽名方案瞒大。

  • v1 是基于 Jar 的簽名方案螃征,它存在完整性覆蓋范圍不足 & 驗證速度較差兩個問題。

  • Android 7.0 推出的 v2 簽名方案優(yōu)化了這兩個問題透敌,通過「條目內容區(qū)」和「中央目錄區(qū)」之間插入「APK 簽名分塊(APK Signing Block)」盯滚,優(yōu)化了 v1 方案的兩大問題。

  • Android 9.0 推出的 v3 方案是 v2 方案的優(yōu)化版本酗电,滿足了密鑰輪換的需求魄藕。


參考資料

創(chuàng)作不易背率,你的「三連」是丑丑最大的動力,我們下次見!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末寝姿,一起剝皮案震驚了整個濱河市交排,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饵筑,老刑警劉巖埃篓,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異根资,居然都是意外死亡架专,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門玄帕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胶征,“玉大人,你說我怎么就攤上這事桨仿【Φ停” “怎么了?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵服傍,是天一觀的道長钱雷。 經常有香客問我,道長吹零,這世上最難降的妖魔是什么罩抗? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮灿椅,結果婚禮上套蒂,老公的妹妹穿的比我還像新娘。我一直安慰自己茫蛹,他們只是感情好操刀,可當我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著婴洼,像睡著了一般骨坑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上柬采,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天欢唾,我揣著相機與錄音,去河邊找鬼粉捻。 笑死礁遣,一個胖子當著我的面吹牛,可吹牛的內容都是我干的肩刃。 我是一名探鬼主播祟霍,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼杏头,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浅碾?” 一聲冷哼從身側響起大州,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎垂谢,沒想到半個月后厦画,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡滥朱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年根暑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徙邻。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡排嫌,死狀恐怖,靈堂內的尸體忽然破棺而出缰犁,到底是詐尸還是另有隱情淳地,我是刑警寧澤,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布帅容,位于F島的核電站颇象,受9級特大地震影響,放射性物質發(fā)生泄漏并徘。R本人自食惡果不足惜遣钳,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望麦乞。 院中可真熱鬧蕴茴,春花似錦、人聲如沸姐直。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽简肴。三九已至晃听,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間砰识,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工佣渴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辫狼,地道東北人。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓辛润,卻偏偏與公主長得像膨处,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,937評論 2 361

推薦閱讀更多精彩內容