在將 App 發佈到市場以前,很重要的一個步驟就是爲 APK 進行簽名,大部分時候,這個操做隱藏在了打包的流程中,而不被咱們注意到。android
簽名的做用,除了證實 App 的全部權以外,還能夠幫助 Android 市場和設備校驗 APK 的正確性git
Android 簽名是自證實的,並不會對證書進行 CA 認證。也就是咱們可使用工具自行生成簽名證書,只要是一個正確的簽名,系統就會認可,而且容許安裝。github
生成簽名的時,能夠指定一個有效時間,這個時間默認爲 25 年,而且 Google Play 也有硬性規定,上架的 App 簽名有效期必須在 2033-10-22 日期以後。因此只要不是手欠修改了這個有效期,在當下這個時刻,是不會有問題,畢竟到如今尚未一款 App 存在 25 年。數組
有些問題不在眼前,倒是真實存在的。對於一款上架的 App,最重要的就是用戶,而當簽名失效以後,咱們只能被迫換籤名,此時由於簽名校驗沒法經過,就會致使舊用戶沒法覆蓋安裝。這些歷史用戶惟一的選擇,就是卸載後從新安裝。安全
好在這不只僅是你個人問題,天塌下來有個子高的頂着,因此別擔憂,Google 已經着手在解決這個問題了。app
方案就是 Android 9.0 新增的對 APK V3 簽名的支持。工具
Android 的簽名方案,發展到如今,不是一蹴而就的。Android 如今已經支持三種應用簽名方案:學習
V1 到 V2 是顛覆性的,爲了解決 JAR 簽名方案的安全性問題,而到了 V3 方案,其實結構上並無太大的調整,能夠理解爲 V2 簽名方案的升級版,有一些資料也把它稱之爲 V2+ 方案。ui
由於這種簽名方案的升級,就是向下兼容的,因此只要使用得當,這個過程對開發者是透明的。spa
V1 到 V2 方案的升級,對開發者影響最大的,就是渠道簽署的問題。在當下這個大環境下,咱們想讓不一樣渠道、市場的安裝包有所區別,攜帶渠道的惟一標識,這就是咱們俗稱的渠道包。好在各大廠都開源了本身的籤渠道方案,例如:Walle(美團)、VasDolly(騰訊)都是很是優秀的方案,想了解的能夠先看看以前的文章:《Android 簽名和多渠道打包原理》。
先從 Android 簽名的歷史講起。
在上個世紀 80 年代,Phil Katz 建立了 ZIP 格式,能夠將文件和一些元數組,組合在一個文件中,便於傳輸和存檔,該格式是爲了解決壓縮、校驗和冗餘頭等問題而提出的解決方案。
Sum 公司在上世紀 90 年代,將 ZIP 做爲 JAR 格式的基礎,而 JAR 本質上就是一個 ZIP 存檔。在其中,META-INF 目錄下會包含一些元數據和簽名數據等信息。
Android 出現後,也沿用了 Java 的 JAR 的發佈方式,將 APK 創建在 JAR 格式之上,在此基礎上對 Dalvik 字節碼 classes.dex 和資源 resources.arsc 等文件添加更多標準化的結構。當時 Android 的 APK 徹底依賴 JAR 的簽名方案來確保應用程序的正確性,這就是咱們俗稱的 V1 方案(JAR 方案)。
在 V1 簽名方案中,並不會保護 APK 內的全部文件,會存在一些例外部分,即使被修改也不會致使簽名失效,例如:ZIP 元數據。同時,V1 方案對 APK 內部被保護的原始文件,是單獨進行計算數據摘要的,因此在驗證時,須要先解壓再驗證,致使安裝時會花費更多的時間,消耗更多的內存。例如 V1 方案中籤渠道的方式就是利用了此特性,將渠道信息寫入 META-INF 文件中,這不會破壞 V1 簽名。
多年後,在 Android 7.0 中添加了一種新的簽名方式,就是咱們俗稱的 V2 方案。V2 簽名提供了更強大的 APK 文件驗證,它再也不檢查包內單個文件,而是檢查整個 APK。它在 ZIP 文件中,插入一個額外的簽名塊,覆蓋 ZIP 文件中的其他部分。
在這個額外的簽名塊(Apk Signature Block V2)中,會對當前 APK 的其餘部分簽名。
從安全的角度 V2 會比 V1 更安全,V2 簽名是驗證整個打包後的 APK 文件,因此對其 APK 文件作「任何」改動都會破壞簽名。注意這裏的任何是帶引號的,V2 簽名的簽名塊實際上是一個 K-V 的結構,能夠向其中插入一些簡單的數據而不破壞 V2 簽名,這就是 V2 方案下,多渠道的方案思路。
在引入 V2 方案的同時,也保證了向後兼容,舊的 JAR 簽名方案仍然在舊的設備(Android 7.0 如下)中生效,而在較新的設備上,也會判斷是否使用 V2 簽名,不是則依然會去校驗 V1 簽名。
V2 方案解決了安全問題以及安裝時驗證的效率問題,可是它並無解決前面提到的換籤名問題。
Android 9.0 中引入了新的簽名方式,它的格式大致和 V2 相似,在 V2 插入的簽名塊(Apk Signature Block V2)中,又添加了一個新快(Attr塊)。
在這個新塊中,會記錄咱們以前的簽名信息以及新的簽名信息,以密鑰轉輪的方案,來作簽名的替換和升級。這意味着,只要舊簽名證書在手,咱們就能夠經過它在新的 APK 文件中,更改簽名。
V3 簽名新增的新塊(attr)存儲了全部的簽名信息,由更小的 Level 塊,以鏈表的形式存儲。
其中每一個節點都包含用於爲以前版本的應用簽名的簽名證書,最舊的簽名證書對應根節點,系統會讓每一個節點中的證書爲列表中下一個證書籤名,從而爲每一個新密鑰提供證據來證實它應該像舊密鑰同樣可信。
這個過程有點相似 CA 證書的證實過程,已安裝的 App 的舊簽名,確保覆蓋安裝的 APK 的新簽名正確,將信任傳遞下去。
Android 的簽名方案,不管怎麼升級,都是要確保向下兼容。
在引入 V3 方案後,Android 9.0 及更高版本中,能夠根據 APK 簽名方案,V3 → V2 → V1 依次嘗試驗證 APK。而較舊的平臺會忽略 V3 簽名並嘗試 V2 簽名,最後纔去驗證 V1 簽名。
整個驗證的過程,以下圖:
須要注意的是,對於覆蓋安裝的狀況,簽名校驗只支持升級,而不支持降級。也就是說設備上安裝了一個使用 V1 簽名的 Apk,可使用 V2 簽名的 Apk 進行覆蓋安裝,反之則不容許。
Android 簽名替換的問題,Google 已經在考慮了,9.0 新增的 V3 簽名方案就是爲了解決簽名替換的。這些,確定都是提早準備。
簽名過時的問題,不須要太擔憂,咱們只須要跟着 Google 的步伐就能夠了。
最後小結一下結論,簽名過時的問題,在 Android 9.0 上新支持的 V3 簽名,已經有解決的方案了。另外:
V3 方案尚未正式開放,在最新版的 Build Tools 版本 28.0.3 中的 Apksigner,尚不支持 V3 的 APK 簽名方案。想嚐鮮能夠經過源代碼自行編譯。
從現有的資料來看,我比較關心的多渠道打包的支持方案,在升級到 V3 以後,舊的 V2 支持的多渠道方案應該依然有效(或者少許改動)。
期待上線後的具體效果。
你對 V3 簽名有什麼想法或者疑問,歡迎在留言區討論。如若本文對你有所幫助,歡迎留言、轉發、點贊。
reference:
Android APK signature scheme V3
公衆號後臺回覆成長『成長』,將會獲得我準備的學習資料,也能回覆『加羣』,一塊兒學習進步;你還能回覆『提問』,向我發起提問。