App 簽名過期或泄露怎麼辦?別擔心,Google 已經給出解決方案!

一、序

在將 App 發佈到市場之前,很重要的一個步驟就是爲 APK 進行簽名,大部分時候,這個操作隱藏在了打包的流程中,而不被我們注意到。

簽名的作用,除了證明 App 的所有權之外,還可以幫助 Android 市場和設備校驗 APK 的正確性

Android 簽名是自證明的,並不會對證書進行 CA 認證。也就是我們可以使用工具自行生成簽名證書,只要是一個正確的簽名,系統就會承認,並且允許安裝。

生成簽名的時,可以指定一個有效時間,這個時間默認爲 25 年,並且 Google Play 也有硬性規定,上架的 App 簽名有效期必須在 2033-10-22 日期之後。所以只要不是手欠修改了這個有效期,在當下這個時刻,是不會有問題,畢竟到現在還沒有一款 App 存在 25 年。

有些問題不在眼前,卻是真實存在的。對於一款上架的 App,最重要的就是用戶,而當簽名失效之後,我們只能被迫換籤名,此時因爲簽名校驗無法通過,就會導致舊用戶無法覆蓋安裝。這些歷史用戶唯一的選擇,就是卸載後重新安裝。

好在這不僅僅是你我的問題,天塌下來有個子高的頂着,所以別擔心,Google 已經着手在解決這個問題了。

方案就是 Android 9.0 新增的對 APK V3 簽名的支持。

二、新的簽名方案 V3

2.1 Android 的簽名方案

Android 的簽名方案,發展到現在,不是一蹴而就的。Android 現在已經支持三種應用簽名方案:

  • V1 方案:基於 JAR 簽名。
  • V2 方案:APK 簽名方案 V2,在 Android 7.0 引入。
  • V3 方案:APK 簽名方案 V3,在 Android 9.0 引入。

V1 到 V2 是顛覆性的,爲了解決 JAR 簽名方案的安全性問題,而到了 V3 方案,其實結構上並沒有太大的調整,可以理解爲 V2 簽名方案的升級版,有一些資料也把它稱之爲 V2+ 方案。

因爲這種簽名方案的升級,就是向下兼容的,所以只要使用得當,這個過程對開發者是透明的。

V1 到 V2 方案的升級,對開發者影響最大的,就是渠道簽署的問題。在當下這個大環境下,我們想讓不同渠道、市場的安裝包有所區別,攜帶渠道的唯一標識,這就是我們俗稱的渠道包。好在各大廠都開源了自己的籤渠道方案,例如:Walle(美團)、VasDolly(騰訊)都是非常優秀的方案,想了解的可以先看看之前的文章:《Android 簽名和多渠道打包原理》。

2.2 簽名的歷史

先從 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 簽名。

image

多年後,在 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 方案解決了安全問題以及安裝時驗證的效率問題,但是它並沒有解決前面提到的換籤名問題。

2.3 Android 的 V3 方案

Android 9.0 中引入了新的簽名方式,它的格式大體和 V2 類似,在 V2 插入的簽名塊(Apk Signature Block V2)中,又添加了一個新快(Attr塊)。

在這個新塊中,會記錄我們之前的簽名信息以及新的簽名信息,以密鑰轉輪的方案,來做簽名的替換和升級。這意味着,只要舊簽名證書在手,我們就可以通過它在新的 APK 文件中,更改簽名。

V3 簽名新增的新塊(attr)存儲了所有的簽名信息,由更小的 Level 塊,以鏈表的形式存儲。

其中每個節點都包含用於爲之前版本的應用簽名的簽名證書,最舊的簽名證書對應根節點,系統會讓每個節點中的證書爲列表中下一個證書籤名,從而爲每個新密鑰提供證據來證明它應該像舊密鑰一樣可信。

這個過程有點類似 CA 證書的證明過程,已安裝的 App 的舊簽名,確保覆蓋安裝的 APK 的新簽名正確,將信任傳遞下去。

2.4 V3 簽名的驗證過程

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 簽名,已經有解決的方案了。另外:

  1. V1 簽名遵循 JAR 的簽名方式,單獨驗證 APK 壓縮包中的文件。
  2. V2 簽名是針對 APK 文件的驗證,將簽名信息寫入簽名塊中,增強了安全性和驗證效率。
  3. V3 簽名在簽名塊中又增加了新塊(attr),由更小的 level 塊,以鏈表的形式存儲多個證書。
  4. 在 V3 方案中,最舊的證書爲新塊鏈表的根節點,以此對新證書籤名,確保新證書正確有效。

V3 方案還沒有正式開放,在最新版的 Build Tools 版本 28.0.3 中的 Apksigner,尚不支持 V3 的 APK 簽名方案。想嚐鮮可以通過源代碼自行編譯。

從現有的資料來看,我比較關心的多渠道打包的支持方案,在升級到 V3 之後,舊的 V2 支持的多渠道方案應該依然有效(或者少量改動)。

期待上線後的具體效果。

你對 V3 簽名有什麼想法或者疑問,歡迎在留言區討論。如若本文對你有所幫助,歡迎留言、轉發、點贊

reference:

Android APK signature scheme V3

Android Doc:應用簽名

Android P V3 簽名新特性


公衆號後臺回覆成長『成長』,將會得到我準備的學習資料,也能回覆『加羣』,一起學習進步;你還能回覆『提問』,向我發起提問。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章