摘要:前幾天,企鵝電競團(tuán)隊(duì)開源了自己的多渠道打包工具,比美團(tuán)的更全面一些。四可商用的多渠道打包方案在開源之前,市面上支持簽名的多渠道打包方案,就屬美團(tuán)的了,下面簡單比對一下它們的優(yōu)缺點(diǎn)。
一、前言
Hi,大家好,我是承香墨影!
當(dāng)我們需要發(fā)布一款 App 到應(yīng)用市場的時(shí)候,一般需要我們針對不同的市場生產(chǎn)不同的渠道包,它們使用的是同一套代碼,只是會包含一些各自的渠道信息,用于我們做數(shù)據(jù)分析。
前幾天,企鵝電競團(tuán)隊(duì)開源了自己的 Android Apk 多渠道打包工具:VasDolly,比美團(tuán)的 Walle 更全面一些。
正好借這個(gè)機(jī)會,來講解一下 Android 的不同版本的簽名機(jī)制的差異。
二、Android 的簽名 2.1 應(yīng)用簽名通過對 Apk 進(jìn)行簽名,開發(fā)者可以證明對 Apk 的所有權(quán)和控制權(quán),可用于安裝和更新其應(yīng)用。而在 Android 設(shè)備上的安裝 Apk ,如果是一個(gè)沒有被簽名的 Apk,則會被拒絕安裝。
在安裝 Apk 的時(shí)候,軟件包管理器也會驗(yàn)證 Apk 是否已經(jīng)被正確簽名,并且通過簽名證書和數(shù)據(jù)摘要驗(yàn)證是否合法沒有被篡改。只有確認(rèn)安全無篡改的情況下,才允許安裝在設(shè)備上。
簡單來說,APK 的簽名主要作用有兩個(gè):
證明 APK 的所有者。
允許 Android 市場和設(shè)備校驗(yàn) APK 的正確性。
而在 Android 中,支持兩種應(yīng)用簽名的方案:
基于 JAR 簽名方案(v1 方案)。
Android Nougat(7.0) 中引入的 APK 簽名方案 v2(v2 方案)。
既然簽名方案在升級,v1 方案一定有一些缺陷的地方,接下來我們先來了解一下這兩個(gè)方案的細(xì)節(jié)。
2.2 v1 簽名方案v1 簽名方案,并不會保護(hù) Apk 內(nèi)的所有內(nèi)容,有一些例外部分,被修改也并不會導(dǎo)致簽名失效。例如:ZIP 元數(shù)據(jù)。
這樣,在驗(yàn)證 APK 簽名的時(shí)候,就需要處理大量不可信(尚未經(jīng)過驗(yàn)證)的數(shù)據(jù)結(jié)構(gòu),然后還需要過濾并舍棄掉這部分不受簽名保護(hù)的數(shù)據(jù),再進(jìn)行簽名校驗(yàn)。也就是說你可以在已簽名的文件中,增加一些不被簽名保護(hù)的內(nèi)容,這將導(dǎo)致受攻擊的可能增大。
另外,v1 方案是對 APK 內(nèi)部的被保護(hù)的原始文件(未壓縮),多帶帶進(jìn)行計(jì)算數(shù)據(jù)摘要,所以在驗(yàn)證期間,也需要對每個(gè)文件進(jìn)行減壓再進(jìn)行簽名校驗(yàn),來驗(yàn)證是否被篡改。所以在驗(yàn)證 APK 簽名的時(shí)候,必須解壓 APK 的所有已壓縮的文件條目進(jìn)行數(shù)據(jù)摘要的校驗(yàn),而這些,都將需要花費(fèi)更多的時(shí)間和內(nèi)存。
正是因?yàn)?v1 方案的缺陷,Android 7.0 開始,才引入了 APK 簽名方案 v2。
2.3 v2 簽名方案APK 簽名方案 v2 是一種全文件的簽名方案,該方案能夠?qū)?APK 所有受保護(hù)的部分進(jìn)行簽名保護(hù),從能能夠發(fā)現(xiàn)它們被篡改。
在 APK 驗(yàn)證期間,v2 方案會將 APK 文件視為 Blob,并對整個(gè)文件進(jìn)行簽名檢查。對 APK 進(jìn)行的任何修改(包括對 ZIP 元數(shù)據(jù)的修改),都會使 APK 簽名作廢。
使用 APK 簽名方案 v2 進(jìn)行簽名時(shí),會在 APK 文件中,插入一個(gè) APK 簽名塊,該分塊位于“ZIP 中央目錄”部分之前并緊鄰該部分。在“APK 簽名分塊”內(nèi),v2 簽名和簽名者身份信息會存儲在?APK 簽名方案 v2 分塊中。
該分塊包含多個(gè) "ID-值" 對,所采用的封裝方式有助于更輕松地在 APK 中找到該分塊。APK 的 v2 簽名會存儲為一個(gè) "ID-值" 對,其中 ID 為 0x7109871a。
上圖是簽名前后,APK 文件結(jié)構(gòu)的對比。可以看到在 v2 已簽名的 APK 中,包含了 4 個(gè)部分。
ZIP 條目的內(nèi)容。
APK 簽名分塊(APK Signing Block)。
ZIP 中央目錄。
ZIP 中央目錄結(jié)尾。
APK 簽名方案 v2 負(fù)責(zé)保護(hù)第 1、3、4 部分的完整性,以及第 2 部分包含的 APK 簽名方案 v2 分塊中的?signed data?分塊的完整性。
第 1、3 和 4 部分的完整性通過其內(nèi)容的一個(gè)或多個(gè)摘要來保護(hù),這些摘要存儲在?signed data?分塊中,而這些分塊則通過一個(gè)或多個(gè)簽名來保護(hù)。
第 1、3 和 4 部分的摘要信息,采用一種類似兩級 Merkle 樹的方式進(jìn)行計(jì)算,所以效率上會提高很多。這個(gè)就比較復(fù)雜了,大家有興趣再深入研究。
既然已經(jīng)有了 v2 方案,我們是否可以完全舍棄 v1 方案,只使用 v2 方案呢?
從官方文檔了解到,因?yàn)?APK 簽名方案 v2 是在 Android 7.0 中引入的,為了使 APK 可以在 Android 6.0 以及更低的版本中正常安裝,應(yīng)該先使用 JAR簽名(v1 簽名)對 APK 進(jìn)行簽名然后再使用 v2 方案對其進(jìn)行簽名。
而在實(shí)際測試中,這種僅使用 v2 方案不使用 v1 方案的情況,是可以編譯通過的,并且在 Android 7.0 之上的設(shè)備上也是可以安裝和運(yùn)行,但是在 7.0 之下,因?yàn)椴粰z測 v2 簽名,而 APK 又不存在 v1 簽名,在安裝的時(shí)候,會提示沒有簽名的錯(cuò)誤。
為了保證兼容性的問題,在 7.0 以上的設(shè)備中,也是兼容了 v1 簽名的方案。所以 v2 簽名方案,暫時(shí)并不是一個(gè)強(qiáng)制的方案。
優(yōu)先級是:優(yōu)先校驗(yàn) v2 方案,沒有或者不存在校驗(yàn)機(jī)制,則校驗(yàn) v1 方案。
2.4 兩種方案對比到這里,我想應(yīng)該對 v1 和 v2 簽名方案應(yīng)該已經(jīng)有一定了解了。v2 簽名既然是升級版,就是為了解決 v1 簽名方案的一些問題。
1、效率問題
v1 方案,會在 /META-INF/MANIFEST.MF 文件中,記錄所有需要校驗(yàn)簽名的文件的數(shù)據(jù)摘要,并且這里生產(chǎn)數(shù)據(jù)摘要是依據(jù)壓縮前的源文件,而在打包的過程中,這些文件又會被壓縮。
所以在驗(yàn)證簽名的過程中,需要先解壓出原始文件,才能計(jì)算數(shù)據(jù)摘要從而驗(yàn)證它,而這個(gè)過程,會消耗更多的時(shí)間和內(nèi)存。
v2 簽名方案,是對 APK 文件本身進(jìn)行數(shù)據(jù)摘要計(jì)算,也就是說它只計(jì)算一個(gè)文件(v1 會計(jì)算 Apk 內(nèi)的很多文件),這樣就不存在解壓 APK 的操作,效率和內(nèi)存都得到優(yōu)化。
2、安全問題
v1 方案,它只會對 APK 內(nèi)部,部分文件進(jìn)行校驗(yàn),并不會對 APK 的完整性進(jìn)行校驗(yàn)。因此,簽名后,我們依然可以修改 APK 文件,例如:美團(tuán)的多渠道方案就是在 /META-INF/ 目錄下,添加一個(gè)空文件,使用文件名來標(biāo)志渠道。
而 v2 簽名是針對整個(gè) APK 進(jìn)行校驗(yàn),所以對 APK 的任何改動,都無法通過 v2 簽名的驗(yàn)證,這樣安全性會更高。
關(guān)于簽名校驗(yàn)的耗時(shí)上,主要影響的是安裝耗時(shí),這里有一份實(shí)驗(yàn)室數(shù)據(jù)(Nexus 6P、Android 7.1.1)可供參考。
差不多 2.x 倍的差距,v2 簽名對 APK 的安裝還是有不少提升的。
三、常見的多渠道方案多渠道的需求點(diǎn),在于同一個(gè) App,需要有一些不同來區(qū)分它們,最常見的場景就是 Android 國內(nèi)的市場,對不同的市場使用不同的渠道包,它們的代碼是一致的,只是一個(gè)渠道號的數(shù)據(jù)不一樣。這樣區(qū)分的好處在于數(shù)據(jù)更清晰,我們知道那個(gè)渠道的用戶是優(yōu)質(zhì)用戶。
3.1 被廢棄的方案既然簽名方案在升級,多渠道的方案也需要升級。曾經(jīng)有一寫可行的方案,基本上已經(jīng)被廢棄了。例如:Gradle Plugin 配置不同的 Flavors、利用 ApkTool 解包改數(shù)據(jù)再重新打包并重新簽名。
這些方案都有一些局限性。例如 Gradle Flavors 方案,每個(gè)渠道都需要重新打包,非常的耗時(shí),并且生成的渠道包 DEX 的 CRC 值都不一致,不利于我們使用熱更新的方案;而 ApkTool 的方案,首先 解包→打包→重新簽名 的過程同樣耗時(shí),其次在于,不穩(wěn)定,可能升級了 Gradle Plugin 的版本之后,會導(dǎo)致解包失敗。
所以我們在想,一個(gè)高效的多渠道打包方案,有幾個(gè)關(guān)鍵單需要注意。
不能破壞簽名。
不能重新打包。
讀取信息,必須高效。
不破壞簽名就限制了不能解包以及重新簽名,勢必對效率有所提高。
而除了 VasDolly 之外,市面上流傳比較廣的就是 美團(tuán) 給出的 Walle 方案,這里就以它們的原理進(jìn)行簡單的講解。
3.2 v1 簽名下的常見多渠道方案v1 下對簽名的校驗(yàn)比較弱了,美團(tuán)給出了完整的解決方案。前面也介紹過,就是在以及打包簽名好的 Apk 中,向 /META-INF 目錄下,寫入一個(gè)空文件,以文件名來標(biāo)識渠道號。
首先,使用這樣的方案,并不會破壞 v1 簽名,所以效率會很高。
而在騰訊的 VasDolly 中,其實(shí)是向 Apk 文件的 EOCD 部分,增加渠道的信息。
APK 文件本質(zhì)上是一個(gè) ZIP 包,而 EOCD 就是上圖所示的第三部分,并且這部分是不被 v1 簽名校驗(yàn)的,可以用來記錄我們的渠道信息。
3.3 v2 簽名下的多渠道方案v2 方案下,其實(shí)騰訊 VasDolly 和美團(tuán)的 Walle 方案,并沒有什么區(qū)別,因?yàn)轵?yàn)證更強(qiáng)了,大家可操作的區(qū)域就只有那么多了。
前面也提到過,使用 v2 簽名后的 APK 文件結(jié)構(gòu)中,插入了一個(gè) APK Signing Block 的簽名塊。
在這個(gè) APK 文件結(jié)構(gòu)下,只有 塊2 ,也就是記錄 APK v2 簽名信息的區(qū)域,不是全部參與 v2 簽名的校驗(yàn),所以大家都在這部分做文章。
APK Signing Block 中包含了多個(gè) "ID-值" 的鍵值對,而 v2 簽名的信息,會記錄在 ID 為 0x7109871a 中,而不會校驗(yàn)其他 ID 下的值。
因此,基于 v2 簽名的多渠道方案就這樣誕生了:在 APK 簽名塊中添加一個(gè)額外的 ID-值,用于記錄渠道信息。
四、可商用的多渠道打包方案在 VasDolly 開源之前,市面上支持 v2 簽名的多渠道打包方案,就屬美團(tuán)的 Walle 了,下面簡單比對一下它們的優(yōu)缺點(diǎn)。
具體你想使用哪種方案,就看你的實(shí)際需要了。
美團(tuán) Walle Github 地址:
https://github.com/Meituan-Di...
Walle 掃碼直達(dá)
騰訊 VasDolly Github 地址:
https://github.com/Tencent/Va...
VasDolly 掃碼直達(dá)
部分圖片來源以及參考資料:
https://source.android.com/se...
https://github.com/Tencent/Va...
https://tech.meituan.com/mt-a...
今天在公眾號后臺回復(fù)成長『成長』,將會得到我整理的一些學(xué)習(xí)資料,也能回復(fù)『加群』,一起學(xué)習(xí)進(jìn)步。
推薦閱讀:
站在Android開發(fā)的角度,聊聊Airbnb的Lottie
漫畫:Git 二分 Debug,火速定位出錯(cuò)代碼!
找了一天找不到 Bug ? 試試 Git 的二分法吧!!!
如何更精準(zhǔn)的在 Github 上搜索開源庫?你需要這些技巧!
Android 開發(fā),遇上 Emoji 頭疼嗎?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68613.html
摘要:宅社,一款純粹的聚合類項(xiàng)目地址出于愛好與學(xué)習(xí)的目的做出了這款風(fēng)格的應(yīng)用,旨意通過涵蓋端的一些熱門技術(shù)框架來打造一個(gè)面向市場級別的產(chǎn)品通過本項(xiàng)目,你可以了解到以下技術(shù)組件化配置混淆多渠道包預(yù)覽應(yīng)用下載體驗(yàn)項(xiàng)目相關(guān)項(xiàng)目環(huán)境項(xiàng)目結(jié)構(gòu)宿主基礎(chǔ)庫 showImg(https://segmentfault.com/img/remote/1460000014524898?w=1280&h=800);...
閱讀 840·2019-08-30 15:55
閱讀 1414·2019-08-30 13:55
閱讀 1993·2019-08-29 17:13
閱讀 2847·2019-08-29 15:42
閱讀 1336·2019-08-26 14:04
閱讀 1025·2019-08-26 13:31
閱讀 3276·2019-08-26 11:34
閱讀 837·2019-08-23 18:25