消息摘要滔金、數(shù)字簽名和數(shù)字證書 Android打包流程 v1 v2 v3簽名對比

Android簽名機(jī)制

什么是Android簽名

了解 HTTPS 通信的同學(xué)都知道霉涨,在消息通信時,必須至少解決兩個問題:一是確保消息來源的真實(shí)性管引,二是確保消息不會被第三方篡改士败。

同理,在安裝 apk 時褥伴,同樣也需要確保 apk 來源的真實(shí)性谅将,以及 apk 沒有被第三方篡改。為了解決這一問題重慢,Android官方要求開發(fā)者對 apk 進(jìn)行簽名饥臂,而簽名就是對apk進(jìn)行加密的過程。要了解如何實(shí)現(xiàn)簽名似踱,需要了解兩個基本概念:消息摘要隅熙、數(shù)字簽名和數(shù)字證書。

消息摘要

消息摘要(Message Digest)核芽,又稱數(shù)字摘要(Digital Digest)或數(shù)字指紋(Finger Print)囚戚。簡單來說,消息摘要就是在消息數(shù)據(jù)上轧简,執(zhí)行一個單向的 Hash 函數(shù)驰坊,生成一個固定長度的Hash值,這個Hash值即是消息摘要哮独。

上面提到的的加密 Hash 函數(shù)就是消息摘要算法拳芙。它有以下特征:

  • 無論輸入的消息有多長,計算出來的消息摘要的長度總是固定的皮璧。 例如:應(yīng)用 MD5 算法摘要的消息有128個比特位舟扎,用 SHA-1 算法摘要的消息最終有 160 比特位的輸出,SHA-1 的變體可以產(chǎn)生 192 比特位和 256 比特位的消息摘要悴务。一般認(rèn)為睹限,摘要的最終輸出越長,該摘要算法就越安全。

  • 消息摘要看起來是「隨機(jī)的」邦泄。 這些比特看上去是胡亂的雜湊在一起的删窒。可以用大量的輸入來檢驗其輸出是否相同顺囊,一般,不同的輸入會有不同的輸出蕉拢,而且輸出的摘要消息可以通過隨機(jī)性檢驗特碳。但是,一個摘要并不是真正隨機(jī)的晕换,因為用相同的算法對相同的消息求兩次摘要午乓,其結(jié)果必然相同;而若是真正隨機(jī)的闸准,則無論如何都是無法重現(xiàn)的益愈。因此消息摘要是「偽隨機(jī)的」。

  • 消息摘要函數(shù)是單向函數(shù)夷家,即只能進(jìn)行正向的信息摘要蒸其,而無法從摘要中恢復(fù)出任何的消息,甚至根本就找不到任何與原信息相關(guān)的信息库快。 當(dāng)然摸袁,可以采用強(qiáng)力攻擊的方法,即嘗試每一個可能的信息义屏,計算其摘要靠汁,看看是否與已有的摘要相同,如果這樣做闽铐,最終肯定會恢復(fù)出摘要的消息蝶怔。但實(shí)際上,要得到的信息可能是無窮個消息之一兄墅,所以這種強(qiáng)力攻擊幾乎是無效的踢星。

  • 好的摘要算法,沒有人能從中找到「碰撞」察迟≌队或者說,無法找到兩條消息扎瓶,使它們的摘要相同所踊。雖然「碰撞」是肯定存在的(由于長明文生成短摘要的 Hash 必然會產(chǎn)生碰撞)。即對于給定的一個摘要概荷,不可能找到一條信息使其摘要正好是給定的秕岛。

正是由于以上特點(diǎn),消息摘要算法被廣泛應(yīng)用在「數(shù)字簽名」領(lǐng)域,作為對明文的摘要算法继薛。著名的消息摘要算法有 RSA 公司的 MD5 算法和 SHA-1 算法及其大量的變體修壕。SHA-256 是 SHA-1 的升級版,現(xiàn)在 Android 簽名使用的默認(rèn)算法都已經(jīng)升級到 SHA-256 了遏考。

正是因為消息摘要具有這種特性慈鸠,很適合來驗證數(shù)據(jù)的完整性。比如:在網(wǎng)絡(luò)傳輸過程中下載一個大文件 BigFile灌具,我們會同時從網(wǎng)絡(luò)下載 BigFile 和 BigFile.md5青团,BigFile.md5 保存 BigFile 的摘要,我們在本地生成 BigFile 的消息摘要和 BigFile.md5 比較咖楣,如果內(nèi)容相同督笆,則表示下載過程正確。

數(shù)字簽名

數(shù)字簽名的作用就是保證信息傳輸?shù)耐暾杂栈摺l(fā)送者的身份認(rèn)證娃肿、防止交易中的抵賴發(fā)生。數(shù)字簽名技術(shù)是將摘要信息用發(fā)送者的私鑰加密珠十,與原文一起傳送給接收者料扰。接收者只有用發(fā)送者的公鑰才能解密被加密的摘要信息然后用HASH函數(shù)對收到的原文產(chǎn)生一個摘要信息,與解密的摘要信息對比宵睦。如果相同记罚,則說明收到的信息是完整的,在傳輸過程中沒有被修改壳嚎,否則說明信息被修改過桐智,因此數(shù)字簽名能夠驗證信息的完整性。

如 RSA 作為數(shù)字簽名方案使用時烟馅,它的使用流程如下:這種簽名實(shí)際上就是用信源的私鑰加密消息说庭,加密后的消息即成了簽體;而用對應(yīng)的公鑰進(jìn)行驗證郑趁,若公鑰解密后的消息與原來的消息相同刊驴,則消息是完整的,否則消息不完整寡润。

RSA正好和公鑰密碼用于消息保密是相反的過程捆憎。因為只有信源才擁有自己地私鑰,別人無法重新加密源消息梭纹,所以即使有人截獲且更改了源消息躲惰,也無法重新生成簽體,因為只有用信源的私鑰才能形成正確地簽體变抽。

同樣信宿只要驗證用信源的公鑰解密的消息是否與明文消息相同础拨,就可以知道消息是否被更改過氮块,而且可以認(rèn)證消息是否是確實(shí)來自意定的信源,還可以使信源不能否認(rèn)曾經(jīng)發(fā)送的消息诡宗。所以 這樣可以完成數(shù)字簽名的功能滔蝉。

但這種方案過于單純,它僅可以保證消息的完整性塔沃,而無法確保消息的保密性蝠引。而且這種方案要對所有的消息進(jìn)行加密操作,這在消息的長度比較大時芳悲,效率是非常低的立肘,主要原因在于公鑰體制的加解密過程的低效性。所以這種方案一般不可取名扛。

幾乎所有的數(shù)字簽名方案都要和快速高效的摘要算法(Hash 函數(shù))一起使用,當(dāng)公鑰算法與摘要算法結(jié)合起來使用時茧痒,便構(gòu)成了一種有效地數(shù)字簽名方案肮韧。

簽名證書

通過數(shù)字簽名技術(shù),確實(shí)可以解決可靠通信的問題旺订。一旦驗簽通過弄企,接收者就能確信該消息是期望的發(fā)送者發(fā)送的,而發(fā)送者也不能否認(rèn)曾經(jīng)發(fā)送過該消息区拳。

大家有沒有注意到拘领,前面講的數(shù)字簽名方法,有一個前提樱调,就是消息的接收者必須事先得到正確的公鑰约素。如果一開始公鑰就被別人篡改了,那壞人就會被你當(dāng)成好人笆凌,而真正的消息發(fā)送者給你發(fā)的消息會被你視作無效的圣猎。而且,很多時候根本就不具備事先溝通公鑰的信息通道乞而。

那么如何保證公鑰的安全可信呢送悔?這就要靠數(shù)字證書來解決了。

數(shù)字證書是一個經(jīng)證書授權(quán)(Certificate Authentication)中心數(shù)字簽名的包含公鑰擁有者信息以及公鑰的文件爪模。數(shù)字證書的格式普遍采用的是 X.509 V3 國際標(biāo)準(zhǔn)欠啤,一個標(biāo)準(zhǔn)的 X.509 數(shù)字證書通常包含以下內(nèi)容: - 證書的發(fā)布機(jī)構(gòu)(Issuer):該證書是由哪個機(jī)構(gòu)(CA 中心)頒發(fā)的。

  • 證書的有效期(Validity):證書的有效期屋灌,或者說使用期限洁段。過了該日期,證書就失效了声滥。

  • 證書所有人的公鑰(Public-Key):該證書所有人想要公布出去的公鑰眉撵。

  • 證書所有人的名稱(Subject):這個證書是發(fā)給誰的侦香,或者說證書的所有者,一般是某個人或者某個公司名稱纽疟、機(jī)構(gòu)的名稱罐韩、公司網(wǎng)站的網(wǎng)址等。

  • 證書所使用的簽名算法(Signature algorithm):這個數(shù)字證書的數(shù)字簽名所使用的加密算法污朽,這樣就可以使用證書發(fā)布機(jī)構(gòu)的證書里面的公鑰散吵,根據(jù)這個算法對指紋進(jìn)行解密。

  • 證書發(fā)行者對證書的數(shù)字簽名(Thumbprint):數(shù)字證書的hash 值(指紋)蟆肆,用于保證數(shù)字證書的完整性矾睦,確保證書沒有被修改過。

數(shù)字證書的原理就是在證書發(fā)布時炎功,CA 機(jī)構(gòu)會根據(jù)簽名算法(Signature algorithm)對整個證書計算其 hash 值(指紋)并和證書放在一起枚冗,使用者打開證書時,自己也根據(jù)簽名算法計算一下證書的 hash 值(指紋)蛇损,如果和證書中記錄的指紋對的上赁温,就說明證書沒有被修改過。

可以看出淤齐,數(shù)字證書本身也用到了數(shù)字簽名技術(shù)股囊,只不過簽名的內(nèi)容是整個證書(里面包含了證書所有者的公鑰以及其他一些內(nèi)容)。與普通數(shù)字簽名不同的是更啄,數(shù)字證書的簽名者不是隨隨便便一個普通機(jī)構(gòu)稚疹,而是 CA 機(jī)構(gòu)。

總結(jié)一下祭务,數(shù)字簽名和簽名驗證的大體流程如下圖所示:

image

Android打包流程

整個Android的打包流程如下圖所示:

image

編譯打包步驟:

1内狗,打包資源文件,生成R.java文件 打包資源的工具是aapt(The Android Asset Packaing Tool)(E:\Documents\Android\sdk\build-tools\25.0.0\aapt.exe)待牵。

在這個過程中其屏,項目中的AndroidManifest.xml文件和布局文件XML都會編譯,然后生成相應(yīng)的R.java缨该,另外AndroidManifest.xml會被aapt編譯成二進(jìn)制偎行。

存放在APP的res目錄下的資源,該類資源在APP打包前大多會被編譯贰拿,變成二進(jìn)制文件蛤袒,并會為每個該類文件賦予一個resource id评雌。對于該類資源的訪問物臂,應(yīng)用層代碼則是通過resource id進(jìn)行訪問的跟狱。Android應(yīng)用在編譯過程中aapt工具會對資源文件進(jìn)行編譯宙攻,并生成一個resource.arsc文件,resource.arsc文件相當(dāng)于一個文件索引表骇扇,記錄了很多跟資源相關(guān)的信息泣矛。

2. 處理aidl文件努酸,生成相應(yīng)的Java文件 這一過程中使用到的工具是aidl(Android Interface Definition Language),即Android接口描述語言(E:\Documents\Android\sdk\build-tools\25.0.0\aidl.exe)锈候。

aidl工具解析接口定義文件然后生成相應(yīng)的Java代碼接口供程序調(diào)用薄料。如果在項目沒有使用到aidl文件,則可以跳過這一步泵琳。

3. 編譯項目源代碼摄职,生成class文件 項目中所有的Java代碼,包括R.java和.aidl文件获列,都會變Java編譯器(javac)編譯成.class文件谷市,生成的class文件位于工程中的bin/classes目錄下。

4. 轉(zhuǎn)換所有的class文件击孩,生成classes.dex文件 dx工具生成可供Android系統(tǒng)Dalvik虛擬機(jī)執(zhí)行的classes.dex文件迫悠,該工具位于(E:\Documents\Android\sdk\build-tools\25.0.0\dx.bat)。

任何第三方的libraries和.class文件都會被轉(zhuǎn)換成.dex文件巩梢。dx工具的主要工作是將Java字節(jié)碼轉(zhuǎn)成成Dalvik字節(jié)碼及皂、壓縮常量池、消除冗余信息等且改。

5. 打包生成APK文件 所有沒有編譯的資源,如images板驳、assets目錄下資源(該類文件是一些原始文件又跛,APP打包時并不會對其進(jìn)行編譯,而是直接打包到APP中若治,對于這一類資源文件的訪問慨蓝,應(yīng)用層代碼需要通過文件名對其進(jìn)行訪問);編譯過的資源和.dex文件都會被apkbuilder工具打包到最終的.apk文件中端幼。

打包的工具apkbuilder位于 android-sdk/tools目錄下礼烈。apkbuilder為一個腳本文件,實(shí)際調(diào)用的是(E:\Documents\Android\sdk\tools\lib)文件中的com.android.sdklib.build.ApkbuilderMain類婆跑。

6. 對APK文件進(jìn)行簽名 一旦APK文件生成此熬,它必須被簽名才能被安裝在設(shè)備上。

在開發(fā)過程中滑进,主要用到的就是兩種簽名的keystore犀忱。一種是用于調(diào)試的debug.keystore,它主要用于調(diào)試扶关,在Eclipse或者Android Studio中直接run以后跑在手機(jī)上的就是使用的debug.keystore阴汇。

另一種就是用于發(fā)布正式版本的keystore。

7. 對簽名后的APK文件進(jìn)行對齊處理 如果你發(fā)布的apk是正式版的話节槐,就必須對APK進(jìn)行對齊處理搀庶,用到的工具是zipalign(E:\Documents\Android\sdk\build-tools\25.0.0\zipalign.exe)

對齊的主要過程是將APK包中所有的資源文件距離文件起始偏移為4字節(jié)整數(shù)倍拐纱,這樣通過內(nèi)存映射訪問apk文件時的速度會更快。對齊的作用就是減少運(yùn)行時內(nèi)存的使用哥倔。

從上圖可以看到秸架,簽名發(fā)生在打包過程中的倒數(shù)第二步,而且簽名針對的是已經(jīng)存在的apk包未斑,并不會影響我們寫的代碼咕宿。事實(shí)也確實(shí)是如此,Android的簽名蜡秽,大致的簽名原理就是對未簽名的apk里面的所有文件計算hash府阀,然后保存起來(MANIFEST.MF),然后在對這些hash計算hash保存起來(CERT.SF)芽突,然后在計算hash试浙,然后再通過我們上面生成的keystore里面的私鑰進(jìn)行加密并保存(CERT.RSA)。

Android簽名方案

Android 系統(tǒng)從誕生到現(xiàn)在的1.0版本寞蚌,一共經(jīng)歷了三代應(yīng)用簽名方案田巴,分別是v1、v2和v3方案挟秤。 - v1 方案:基于 JAR 簽名壹哺。 - v2 方案:APK 簽名方案 v2,在 Android 7.0 引入艘刚。 - v3 方案:APK 簽名方案v3管宵,在 Android 9.0 引入。

其中攀甚,v1 到 v2 是顛覆性的箩朴,主要是為了解決 JAR 簽名方案的安全性問題,而到了 v3 方案秋度,其實(shí)結(jié)構(gòu)上并沒有太大的調(diào)整炸庞,可以理解為 v2 簽名方案的升級版。

v1 到 v2 方案的升級荚斯,對開發(fā)者影響是最大的埠居,就是渠道簽署的問題。v2的簽名也是為了讓不同渠道鲸拥、市場的安裝包有所區(qū)別拐格,攜帶渠道的唯一標(biāo)識,也即是我們俗稱的渠道包刑赶。好在各大廠都開源了自己的簽渠道方案捏浊,例如:Walle(美團(tuán))、VasDolly(騰訊)都是非常優(yōu)秀的方案撞叨。

V1簽名

簽名工具

Android 應(yīng)用的簽名工具有兩種:jarsigner 和 apksigner金踪。它們的簽名算法沒什么區(qū)別浊洞,主要是簽名使用的文件不同。它們的區(qū)別如下:

  • jarsigner:jdk 自帶的簽名工具胡岔,可以對 jar 進(jìn)行簽名法希。使用 keystore 文件進(jìn)行簽名。生成的簽名文件默認(rèn)使用 keystore 的別名命名靶瘸。

  • apksigner:Android sdk 提供的專門用于 Android 應(yīng)用的簽名工具苫亦。使用 pk8、x509.pem 文件進(jìn)行簽名怨咪。其中 pk8 是私鑰文件屋剑,x509.pem 是含有公鑰的文件。生成的簽名文件統(tǒng)一使用“CERT”命名诗眨。

既然這兩個工具都是給 APK 簽名的唉匾,那么 keystore 文件和 pk8,x509.pem 他們之間是不是有什么聯(lián)系呢匠楚?答案是肯定的巍膘,他們之間是可以轉(zhuǎn)化的,這里就不再分析它們是如何進(jìn)行轉(zhuǎn)化芋簿,網(wǎng)上的例子很多峡懈。

還有一個需要注意的知識點(diǎn),如果我們查看一個keystore 文件的內(nèi)容与斤,會發(fā)現(xiàn)里面包含有一個 MD5 和 SHA1 摘要逮诲,這個就是 keystore 文件中私鑰的數(shù)據(jù)摘要,這個信息也是我們在申請很多開發(fā)平臺賬號時需要填入的信息幽告。

簽名過程

首先,我們?nèi)我膺x取一個簽名后的 APK(Sample-release.APK)進(jìn)行解壓裆甩,會得到如下圖所示的文件冗锁。

image

可以發(fā)現(xiàn),在 META-INF 文件夾下有三個文件:MANIFEST.MF嗤栓、CERT.SF冻河、CERT.RSA。它們就是簽名過程中生成的文件茉帅,它們的作用如下叨叙。

MANIFEST.MF

該文件中保存的其實(shí)就是逐一遍歷 APK 中的所有條目,如果是目錄就跳過堪澎,如果是一個文件擂错,就用 SHA1(或者 SHA256)消息摘要算法提取出該文件的摘要然后進(jìn)行 BASE64 編碼后,作為「SHA1-Digest」屬性的值寫入到 MANIFEST.MF 文件中的一個塊中樱蛤。該塊有一個「Name」屬性钮呀, 其值就是該文件在 APK 包中的路徑剑鞍。

打開MANIFEST.MF文件,文件內(nèi)容如下圖:

image

CERT.SF

打開CERT.SF文件爽醋,文件的內(nèi)容如下:

image
  • SHA1-Digest-Manifest-Main-Attributes:對 MANIFEST.MF 頭部的塊做 SHA1(或者SHA256)后再用 Base64 編碼蚁署。 - SHA1-Digest-Manifest:對整個 MANIFEST.MF 文件做 SHA1(或者 SHA256)后再用 Base64 編碼。 - SHA1-Digest:對 MANIFEST.MF 的各個條目做 SHA1(或者 SHA256)后再用 Base64 編碼蚂四。

CERT.RSA

把之前生成的 CERT.SF 文件用私鑰計算出簽名, 然后將簽名以及包含公鑰信息的數(shù)字證書一同寫入 CERT.RSA 中保存光戈。需要注意的是,Android APK 中的 CERT.RSA 證書是自簽名的遂赠,并不需要第三方權(quán)威機(jī)構(gòu)發(fā)布或者認(rèn)證的證書久妆,用戶可以在本地機(jī)器自行生成這個自簽名證書。Android 目前不對應(yīng)用證書進(jìn)行 CA 認(rèn)證解愤。 打開CERT.RSA文件镇饺,內(nèi)容如下圖:

image

這里看到的都是二進(jìn)制文件,因為 使用RSA 加密了送讲,所以我們需要用 openssl 命令才能查看其內(nèi)容奸笤,如下所示。

$ openssl pkcs7 -inform DER -in /<文件存放路徑>/Sample-release_new/original/META-INF/CERT.RSA -text -noout -print_certs

執(zhí)行上面的命令后哼鬓,得到的內(nèi)容如下圖:

image

綜上可以看出监右,一個完整的簽名過程如下圖:

image

簽名校驗

簽名驗證是發(fā)生在 APK 的安裝過程中,一共分為三步:

  1. 檢查 APK 中包含的所有文件异希,對應(yīng)的摘要值與 MANIFEST.MF 文件中記錄的值一致健盒。
  2. 使用證書文件(RSA 文件)檢驗簽名文件(SF 文件)沒有被修改過。
  3. 使用簽名文件(SF 文件)檢驗 MF 文件沒有被修改過称簿。

綜上所述扣癣,一個完整的簽名驗證過程如下所示:

image

V2簽名

APK 簽名方案 v2 是一種全文件簽名方案,該方案能夠發(fā)現(xiàn)對 APK 的受保護(hù)部分進(jìn)行的所有更改憨降,從而有助于加快驗證速度并增強(qiáng)完整性保證父虑。通過前面的分析,可以發(fā)現(xiàn) v1 簽名有兩個地方可以改進(jìn): - 簽名校驗速度慢 校驗過程中需要對apk中所有文件進(jìn)行摘要計算授药,在 APK 資源很多士嚎、性能較差的機(jī)器上簽名校驗會花費(fèi)較長時間,導(dǎo)致安裝速度慢悔叽。

  • 完整性保障不夠 META-INF 目錄用來存放簽名莱衩,自然此目錄本身是不計入簽名校驗過程的,可以隨意在這個目錄中添加文件娇澎,比如一些快速批量打包方案就選擇在這個目錄中添加渠道文件笨蚁。

為了解決這兩個問題,在 Android 7.0 版本 中引入了全新的 APK Signature Scheme v2。

V2的改進(jìn)

由于在 v1 僅針對單個 ZIP 條目進(jìn)行驗證赚窃,因此册招,在 APK 簽署后可進(jìn)行許多修改 — 可以移動甚至重新壓縮文件。事實(shí)上勒极,編譯過程中要用到的 ZIPalign 工具就是這么做的是掰,它用于根據(jù)正確的字節(jié)限制調(diào)整 ZIP 條目,以改進(jìn)運(yùn)行時性能辱匿。而且我們也可以利用這個東西键痛,在打包之后修改 META-INF 目錄下面的內(nèi)容,或者修改 ZIP 的注釋來實(shí)現(xiàn)多渠道的打包匾七,在 v1 簽名中都可以校驗通過絮短。

v2 簽名將驗證歸檔中的所有字節(jié),而不是單個 ZIP 條目昨忆,因此丁频,在簽署后無法再運(yùn)行 ZIPalign(必須在簽名之前執(zhí)行)。正因如此邑贴,現(xiàn)在席里,在編譯過程中,Google 將壓縮拢驾、調(diào)整和簽署合并成一步完成奖磁。

v2 簽名

v2 簽名會在原先 APK 塊中增加了一個新的塊(簽名塊),新的塊存儲了簽名繁疤、摘要咖为、簽名算法、證書鏈和額外屬性等信息稠腊,這個塊有特定的格式躁染。最終的簽名APK其實(shí)就有四塊:頭文件區(qū)、V2簽名塊架忌、中央目錄褐啡、尾部。下圖是V1簽名和V2簽名的組成鳖昌。

image

整個簽名塊的格式如下:

  • size of block,以字節(jié)數(shù)(不含此字段)計 (uint64)
  • 帶 uint64 長度前綴的“ID-值”對序列:
  • size of block低飒,以字節(jié)數(shù)計 - 與第一個字段相同 (uint64)
  • magic“APK 簽名分塊 42”(16 個字節(jié))

在多個“ID-值”對中许昨,APK簽名信息的 ID 為 0x7109871a,包含的內(nèi)容如下: 帶長度前綴的 signer:

  • 帶長度前綴的 signed data褥赊,包含digests序列糕档,X.509 certificates 序列,additional attributes序列
  • 帶長度前綴的 signatures(帶長度前綴)序列
  • 帶長度前綴的 public key(SubjectPublicKeyInfo,ASN.1 DER 形式)
  • value可能會包含多個 signer速那,因為Android允許多個簽名俐银。

總結(jié)一下:一個簽名塊,可以包含多個ID-VALUE端仰,APK的簽名信息會存放在 ID 為 0x7109871a的鍵值對里捶惜。他的內(nèi)容可以包含多個簽名者的簽名信息,每個簽名信息下包含signed data荔烧、signatures吱七、public key,其中鹤竭,signed data主要存放摘要序列踊餐、證書鏈、額外屬性臀稚,signatures包含多個簽名算法計算出來的簽名值吝岭,public key表示簽名者公鑰,用于校驗的時候驗證簽名的吧寺。

簽名過程

首先窜管,說一下 APK 摘要計算規(guī)則,對于每個摘要算法撮执,計算結(jié)果如下:

  • 將 APK 中文件 ZIP 條目的內(nèi)容微峰、ZIP 中央目錄、ZIP 中央目錄結(jié)尾按照 1MB 大小分割成一些小塊抒钱。
  • 計算每個小塊的數(shù)據(jù)摘要蜓肆,數(shù)據(jù)內(nèi)容是 0xa5 + 塊字節(jié)長度 + 塊內(nèi)容。
  • 計算整體的數(shù)據(jù)摘要谋币,數(shù)據(jù)內(nèi)容是 0x5a + 數(shù)據(jù)塊的數(shù)量 + 每個數(shù)據(jù)塊的摘要內(nèi)容

總之仗扬,就是把 APK 按照 1M 大小分割,分別計算這些分段的摘要蕾额,最后把這些分段的摘要在進(jìn)行計算得到最終的摘要也就是 APK 的摘要早芭。然后將 APK 的摘要 + 數(shù)字證書 + 其他屬性生成簽名數(shù)據(jù)寫入到 APK Signing Block 區(qū)塊。

image

簽名校驗過程

接下來我們來看一下v2簽名的校驗過程诅蝶,整體大概流程如下圖所示退个。

image

其中, v2 簽名機(jī)制是在 Android 7.0 以及以上版本才支持的调炬。因此對于 Android 7.0 以及以上版本语盈,在安裝過程中,如果發(fā)現(xiàn)有 v2 簽名塊缰泡,則必須走 v2 簽名機(jī)制刀荒,不能繞過。否則降級走 v1 簽名機(jī)制。v1 和 v2 簽名機(jī)制是可以同時存在的缠借,其中對于 v1 和 v2 版本同時存在的時候干毅,v1 版本的 META_INF 的 .SF 文件屬性當(dāng)中有一個 X-Android-APK-Signed 屬性。

X-Android-APK-Signed: 2

之前的渠道包生成方案是通過在 META-INF 目錄下添加空文件泼返,用空文件的名稱來作為渠道的唯一標(biāo)識硝逢。但在新的應(yīng)用簽名方案下 META-INF 已經(jīng)被列入了保護(hù)區(qū)了,向 META-INF 添加空文件的方案會對區(qū)塊 1符隙、3趴捅、4 都會有影響。對于這個問題霹疫,可以參考美團(tuán)多渠道打包總結(jié)拱绑。

V3簽名

新版v3簽名在v2的基礎(chǔ)上,仍然采用檢查整個壓縮包的校驗方式丽蝎。不同的是在簽名部分增可以添加新的證書(Attr塊)猎拨。在這個新塊中,會記錄我們之前的簽名信息以及新的簽名信息屠阻,以密鑰轉(zhuǎn)輪的方案红省,來做簽名的替換和升級。這意味著国觉,只要舊簽名證書在手吧恃,我們就可以通過它在新的 APK 文件中,更改簽名麻诀。

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

其中每個節(jié)點(diǎn)都包含用于為之前版本的應(yīng)用簽名的簽名證書呻率,最舊的簽名證書對應(yīng)根節(jié)點(diǎn),系統(tǒng)會讓每個節(jié)點(diǎn)中的證書為列表中下一個證書簽名呻引,從而為每個新密鑰提供證據(jù)來證明它應(yīng)該像舊密鑰一樣可信礼仗。

簽名校驗過程

Android 的簽名方案,無論怎么升級逻悠,都是要確保向下兼容元践。因此,在引入 v3 方案后童谒,Android 9.0 及更高版本中单旁,可以根據(jù) APK 簽名方案,v3 -> v2 -> v1 依次嘗試驗證 APK惠啄。而較舊的平臺會忽略 v3 簽名并嘗試 v2 簽名,最后才去驗證 v1 簽名。 整個驗證的過程撵渡,如下圖:

image

需要注意的是融柬,對于覆蓋安裝的情況,簽名校驗只支持升級趋距,而不支持降級粒氧。也就是說設(shè)備上安裝了一個使用 v1 簽名的 APK,可以使用 v2 簽名的 APK 進(jìn)行覆蓋安裝节腐,反之則不允許外盯。關(guān)于V3簽名的更多知識,可以參考下面的文章:Android v3簽名新特性

原文地址:https://zhuanlan.zhihu.com/p/89126018

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翼雀,一起剝皮案震驚了整個濱河市饱苟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌狼渊,老刑警劉巖箱熬,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異狈邑,居然都是意外死亡城须,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門米苹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糕伐,“玉大人,你說我怎么就攤上這事蘸嘶×记疲” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵亏较,是天一觀的道長莺褒。 經(jīng)常有香客問我,道長雪情,這世上最難降的妖魔是什么遵岩? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮巡通,結(jié)果婚禮上尘执,老公的妹妹穿的比我還像新娘。我一直安慰自己宴凉,他們只是感情好誊锭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著弥锄,像睡著了一般丧靡。 火紅的嫁衣襯著肌膚如雪蟆沫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天温治,我揣著相機(jī)與錄音饭庞,去河邊找鬼。 笑死熬荆,一個胖子當(dāng)著我的面吹牛舟山,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播卤恳,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼累盗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了突琳?” 一聲冷哼從身側(cè)響起若债,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎本今,沒想到半個月后拆座,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冠息,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年挪凑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逛艰。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡躏碳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出散怖,到底是詐尸還是另有隱情菇绵,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布镇眷,位于F島的核電站咬最,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏欠动。R本人自食惡果不足惜永乌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望具伍。 院中可真熱鬧翅雏,春花似錦、人聲如沸人芽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萤厅。三九已至橄抹,卻和暖如春靴迫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背楼誓。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工矢劲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人慌随。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像躺同,于是被迫代替她去往敵國和親阁猜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355