背景
最近在調研一個測試工具的使用,在使用中發現被測試工具處理過的apk文件經安裝后打開就會崩潰,分析崩潰日志后原因是簽名不一致導致的。
說到Android中的簽名,可能大家都知道簽名的目的就是為了保護apk文件的安全,如果apk被惡意篡改后經過安裝校驗的時候,就會出現校驗失敗,導致安裝包安裝失敗的情況。但如果更深去問一下Android簽名機制和原理,是不是就被問住了?接下來的就讓我們去探究Android簽名機制和原理。
Android 簽名機制和原理
Android系統在安裝APK的時候,首先會檢驗APK的簽名,如果發現簽名文件不存在或者校驗簽名失敗,則會拒絕安裝,所以應用程序在發布之前一定要進行簽名。給APK簽名可以帶來以下好處:
應用程序升級如果想無縫升級一個應用,Android系統要求應用程序的新版本與老版本具有相同的簽名與包名。若包名相同而簽名不同,系統會拒絕安裝新版應用。
應用程序模塊化Android系統可以允許同一個證書簽名的多個應用程序在一個進程里運行,系統實際把他們作為一個單個的應用程序。此時就可以把我們的應用程序以模塊的方式進行部署,而用戶可以獨立的升級其中的一個模塊。
代碼或數據共享Android提供了基于簽名的權限機制,一個應用程序可以為另一個以相同證書簽名的應用程序公開自己的功能與數據,同時其它具有不同簽名的應用程序不可訪問相應的功能與數據。
應用程序的可認定性簽名信息中包含有開發者信息,在一定程度上可以防止應用被偽造。例如網易云加密對Android APK加殼保護中使用的“校驗簽名(防二次打包)”功能就是利用了這一點。
簽名的目的:
1. 對發送者的身份認證:
由于開發商可能通過使用相同的package name來混淆替換已經安裝的程序,以此保證簽名不同的包不被替換。
2. 保證信息傳輸的完成性:
簽名對于包中的每個文件進行處理,以此確保包中內容不被替換。
3. 防止交易中的抵賴發生,market對軟件的要求。
簽名原理:
簡單來說總體分為以下幾個步驟:
1. 對Apk中的每個文件做一次算法(數據摘要+Base64編碼),保存到MAINFEST.MF
2. 對MAINFEST.MF整個文件做一次算法(數據摘要+B阿瑟64編碼),存放到CERT.SF文件的頭屬性中,在對MAINFEST.MF文件中各個屬性塊做一次算法(數據摘要+Base64編碼),存放到一個屬性塊中。
3. 對CERT.SF文件做簽名,內容存檔到CERT.RSA中
對一個APK文件簽名之后,APK文件根目錄下會增加META-INF目錄,該目錄下增加三個文件,分別是:MANIFEST.MF、CERT.SF和CERT.RSA,以下是具體的流程:
MANIFEST.MF
這是摘要文件,文件中保存了APK里面所有文件的SHA1校驗值的BASE64編碼,格式如下(一個文件對應一條記錄)。如果改變了APK包中的文件,在apk安裝校驗時,改變后的文件摘要信息與 MANIFEST.MF 的檢驗信息不同,程序就不會安裝成功。假如攻擊者修改了程序的內容,又重新生成了新的摘要,就可以通過驗證。
Name: AndroidMainfest.xmlSHA1-Digest: incCj47jcu56R8pKV8dLACZBKD8=Name: META-INF/android.arch.core_runtime.versionSHA1-Digest: BeF7ZGqBckDCBhhvlPj0xwl01dw=
CERT.SF
這是對摘要的簽名文件,對前一步生成的MANIFEST.MF,使用SHA1-RSA算法,用開發者的私鑰進行簽名。在安裝時只能使用公鑰才能進行解密。解密之后,與未加密的MANIFEST.MF進行對比,如果相符,則表明內容沒有被異常修改。如果在這一步,開發者修改了程序內容,并生成了新的摘要文件,但是攻擊者沒有開發者的私鑰,所以不能生成正確的簽名文件。系統在對程序進行驗證的時候,用開發者公鑰對不正確的簽名文件進行解密,得到的結果和摘要文件對應不起來,導致不能通過檢驗,不能成功安裝文件。文件格式如下:
Name:?AndroidMainfest.xmlSHA1-Digest:?SyFsd2VUpCg4nq8jSOB7dBwuMyI=Name:?META-INF/android.arch.core_runtime.versionSHA1-Digest:?OPQCkzMXJVPQryHeMowVNZmfRMw=
CERT.RSA
該文件中保存了公鑰、所采用的加密算法等信息。
從上面的內容來看,Android系統就是根據這三個文件的內容對APK文件進行簽名檢驗的。