原文:https://blog.csdn.net/freekiteyu/article/details/84849651
一屁奏、什么是簽名?
要想知道簽名是什么当纱,先來看為什么需要簽名 壹瘟?
了解 HTTPS 通信的同學應(yīng)該知道总寻,在消息通信時搀军,必須至少解決兩個問題:一是確保消息來源的真實性连霉,二是確保消息不會被第三方篡改。在安裝 APK 時佛呻,同樣需要確保 APK 來源的真實性裳朋,以及 APK 沒有被第三方篡改。如何解決這兩個問題呢吓著?方法就是開發(fā)者對 APK 進行簽名:在 APK 中寫入一個“指紋”鲤嫡。指紋寫入以后氧苍,APK 中有任何修改,都會導致這個指紋無效泛范,Android 系統(tǒng)在安裝 APK 進行簽名校驗時就會不通過让虐,從而保證了安全性。
要了解如何實現(xiàn)簽名罢荡,需要了解兩個基本概念:消息摘要赡突、數(shù)字簽名和數(shù)字證書。
1.1 消息摘要(Message Digest)
消息摘要(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 比特位的消息摘要派敷。一般認為蛹批,摘要的最終輸出越長,該摘要算法就越安全篮愉。
-
消息摘要看起來是“隨機的”腐芍。
這些比特看上去是胡亂的雜湊在一起的∈怎铮可以用大量的輸入來檢驗其輸出是否相同猪勇,一般,不同的輸入會有不同的輸出冗酿,而且輸出的摘要消息可以通過隨機性檢驗埠对。但是,一個摘要并不是真正隨機的裁替,因為用相同的算法對相同的消息求兩次摘要项玛,其結(jié)果必然相同;而若是真正隨機的弱判,則無論如何都是無法重現(xiàn)的襟沮。因此消息摘要是“偽隨機的”。
-
消息摘要函數(shù)是單向函數(shù),即只能進行正向的信息摘要开伏,而無法從摘要中恢復出任何的消息膀跌,甚至根本就找不到任何與原信息相關(guān)的信息。
當然固灵,可以采用強力攻擊的方法捅伤,即嘗試每一個可能的信息仍秤,計算其摘要,看看是否與已有的摘要相同圈澈,如果這樣做喷橙,最終肯定會恢復出摘要的消息疙剑。但實際上轿曙,要得到的信息可能是無窮個消息之一您单,所以這種強力攻擊幾乎是無效的染服。
-
好的摘要算法叨恨,沒有人能從中找到“碰撞”柳刮。或者說痒钝,無法找到兩條消息秉颗,使它們的摘要相同。
雖然“碰撞”是肯定存在的(由于長明文生成短摘要的Hash必然會產(chǎn)生碰撞)送矩。即對于給定的一個摘要蚕甥,不可能找到一條信息使其摘要正好是給定的。
正是由于以上特點栋荸,消息摘要算法被廣泛應(yīng)用在“數(shù)字簽名”領(lǐng)域菇怀,作為對明文的摘要算法。著名的消息摘要算法有 RSA 公司的 MD5 算法和 SHA-1 算法及其大量的變體晌块。
SHA-256 是 SHA-1 的升級版爱沟,現(xiàn)在 Android 簽名使用的默認算法都已經(jīng)升級到 SHA-256 了。
消息摘要的這種特性匆背,很適合來驗證數(shù)據(jù)的完整性呼伸。比如:在網(wǎng)絡(luò)傳輸過程中下載一個大文件 BigFile,我們會同時從網(wǎng)絡(luò)下載 BigFile 和 BigFile.md5钝尸,BigFile.md5 保存 BigFile 的摘要括享,我們在本地生成 BigFile 的消息摘要和 BigFile.md5 比較,如果內(nèi)容相同珍促,則表示下載過程正確铃辖。
注意,消息摘要只能保證消息的完整性踢星,并不能保證消息的不可篡改性澳叉。
1.2 數(shù)字簽名(Digital Signature)
數(shù)字簽名方案是一種以電子形式存儲消息簽名的方法隙咸。一個完整的數(shù)字簽名方案應(yīng)該由兩部分組成:簽名算法和驗證算法。在講數(shù)字簽名之前成洗,我們先簡單介紹幾個相關(guān)知識點:“公鑰密碼體制”五督、“對稱加密算法”、“非對稱加密算法”瓶殃。
1.2.1 公鑰密碼體制(public-key cryptography)
公鑰密碼體制分為三個部分充包,公鑰、私鑰遥椿、加密解密算法基矮,它的加密解密過程如下:
- 加密:通過加密算法和公鑰對內(nèi)容(或者說明文)進行加密,得到密文冠场。加密過程需要用到公鑰家浇。
- 解密:通過解密算法和私鑰對密文進行解密,得到明文碴裙。解密過程需要用到解密算法和私鑰钢悲。注意,由公鑰加密的內(nèi)容舔株,只能由私鑰進行解密莺琳,也就是說,由公鑰加密的內(nèi)容载慈,如果不知道私鑰惭等,是無法解密的。
公鑰密碼體制的公鑰和算法都是公開的(這是為什么叫公鑰密碼體制的原因)办铡,私鑰是保密的辞做。大家都以使用公鑰進行加密,但是只有私鑰的持有者才能解密料扰。在實際 的使用中凭豪,有需要的人會生成一對公鑰和私鑰,把公鑰發(fā)布出去給別人使用晒杈,自己保留私鑰。目前使用最廣泛的公鑰密碼體制是RSA密碼體制孔厉。
1.2.2 對稱加密算法(symmetric key algorithms)
在對稱加密算法中拯钻,加密和解密都是使用的同一個密鑰。因此對稱加密算法要保證安全性的話撰豺,密鑰要做好保密粪般,只能讓使用的人知道,不能對外公開污桦。
1.2.3 非對稱加密算法(asymmetric key algorithms)
在非對稱加密算法中亩歹,加密使用的密鑰和解密使用的密鑰是不相同的。前面所說的公鑰密碼體制就是一種非對稱加密算法,它的公鑰和是私鑰是不能相同的小作,也就是說加密使用的密鑰和解密使用的密鑰不同亭姥,因此它是一個非對稱加密算法。
1.2.4 RSA 簡介
RSA 密碼體制是一種公鑰密碼體制顾稀,公鑰公開达罗,私鑰保密,它的加密解密算法是公開的静秆。 由公鑰加密的內(nèi)容可以并且只能由私鑰進行解密粮揉,而由私鑰加密的內(nèi)容可以并且只能由公鑰進行解密。也就是說抚笔,RSA 的這一對公鑰扶认、私鑰都可以用來加密和解密,并且一方加密的內(nèi)容可以由并且只能由對方進行解密殊橙。
- 加密:公鑰加密辐宾,私鑰解密的過程,稱為“加密”蛀柴。因為公鑰是公開的螃概,任何公鑰持有者都可以將想要發(fā)送給私鑰持有者的信息進行加密后發(fā)送,而這個信息只有私鑰持有者才能解密鸽疾。
- 簽名: 私鑰加密吊洼,公鑰解密的過程,稱為“簽名”制肮。它和加密有什么區(qū)別呢冒窍?因為公鑰是公開的,所以任何持有公鑰的人都能解密私鑰加密過的密文豺鼻,所以這個過程并不能保證消息的安全性综液,但是它卻能保證消息來源的準確性和不可否認性,也就是說儒飒,如果使用公鑰能正常解密某一個密文谬莹,那么就能證明這段密文一定是由私鑰持有者發(fā)布的,而不是其他第三方發(fā)布的桩了,并且私鑰持有者不能否認他曾經(jīng)發(fā)布過該消息附帽。故此將該過程稱為“簽名”。
1.2.5 數(shù)字簽名
事實上井誉,任何一個公鑰密碼體制都可以單獨地作為一種數(shù)字簽名方案使用蕉扮。如RSA作為數(shù)字簽名方案使用時,可以定義如下:
這種簽名實際上就是用信源的私鑰加密消息颗圣,加密后的消息即成了簽體喳钟;而用對應(yīng)的公鑰進行驗證屁使,若公鑰解密后的消息與原來的消息相同,則消息是完整的奔则,否則消息不完整蛮寂。
它正好和公鑰密碼用于消息保密是相反的過程。因為只有信源才擁有自己地私鑰应狱,別人無法重新加密源消息共郭,所以即使有人截獲且更改了源消息,也無法重新生成簽體疾呻,因為只有用信源的私鑰才能形成正確地簽體除嘹。
同樣信宿只要驗證用信源的公鑰解密的消息是否與明文消息相同,就可以知道消息是否被更改過岸蜗,而且可以認證消息是否是確實來自意定的信源尉咕,還可以使信源不能否認曾經(jīng)發(fā)送的消息。所以 這樣可以完成數(shù)字簽名的功能璃岳。
但這種方案過于單純年缎,它僅可以保證消息的完整性,而無法確保消息的保密性铃慷。而且這種方案要對所有的消息進行加密操作单芜,這在消息的長度比較大時,效率是非常低的犁柜,主要原因在于公鑰體制的加解密過程的低效性洲鸠。所以這種方案一般不可取。
幾乎所有的數(shù)字簽名方案都要和快速高效的摘要算法(Hash函數(shù))一起使用馋缅,當公鑰算法與摘要算法結(jié)合起來使用時扒腕,便構(gòu)成了一種有效地數(shù)字簽名方案。
這個過程是:
- 用摘要算法對消息進行摘要萤悴。
- 再把摘要值用信源的私鑰加密瘾腰。
通過以上兩步得到的消息就是所謂的原始信息的數(shù)字簽名,發(fā)送者需要將原始信息和數(shù)字簽名一同發(fā)送給接收者覆履。而接收者在接收到原始信息和數(shù)字簽名后蹋盆,通過以下 3 步驗證消息的真?zhèn)危?/p>
先把接收到的原始消息用同樣的摘要算法摘要,形成“準簽體”硝全。
對附加上的那段數(shù)字簽名怪嫌,使用預(yù)先得到的公鑰解密。
比較前兩步所得到的兩段消息是否一致柳沙。如果一致,則表明消息確實是期望的發(fā)送者發(fā)的拌倍,且內(nèi)容沒有被篡改過赂鲤;相反噪径,如果不一致,則表明傳送的過程中一定出了問題数初,消息不可信找爱。
這種方法使公鑰加密只對消息摘要進行操作,因為一種摘要算法的摘要消息長度是固定的泡孩,而且都比較“短”(相對于消息而言)车摄,正好符合公鑰加密的要求。這樣效率得到了提高仑鸥,而其安全性也并未因為使用摘要算法而減弱吮播。
綜上所述,數(shù)字簽名是非對稱加密技術(shù) + 消息摘要技術(shù)的結(jié)合眼俊。
1.3 數(shù)字證書(Digital Certificate)
通過數(shù)字簽名技術(shù)意狠,確實可以解決可靠通信的問題。一旦驗簽通過疮胖,接收者就能確信該消息是期望的發(fā)送者發(fā)送的环戈,而發(fā)送者也不能否認曾經(jīng)發(fā)送過該消息。
大家有沒有注意到澎灸,前面講的數(shù)字簽名方法院塞,有一個前提,就是消息的接收者必須事先得到正確的公鑰性昭。如果一開始公鑰就被別人篡改了拦止,那壞人就會被你當成好人,而真正的消息發(fā)送者給你發(fā)的消息會被你視作無效的巩梢。而且创泄,很多時候根本就不具備事先溝通公鑰的信息通道。
那么如何保證公鑰的安全可信呢括蝠?這就要靠數(shù)字證書來解決了鞠抑。
數(shù)字證書是一個經(jīng)證書授權(quán)(Certificate Authentication)中心數(shù)字簽名的包含公鑰擁有者信息以及公鑰的文件。數(shù)字證書的格式普遍采用的是 X.509 V3 國際標準忌警,一個標準的 X.509 數(shù)字證書通常包含以下內(nèi)容:
-
證書的發(fā)布機構(gòu)(Issuer)
該證書是由哪個機構(gòu)(CA中心)頒發(fā)的搁拙。
-
證書的有效期(Validity)
證書的有效期,或者說使用期限法绵。過了該日期箕速,證書就失效了。
-
證書所有人的公鑰(Public-Key)
該證書所有人想要公布出去的公鑰朋譬。
-
證書所有人的名稱(Subject)
這個證書是發(fā)給誰的盐茎,或者說證書的所有者,一般是某個人或者某個公司名稱徙赢、機構(gòu)的名稱字柠、公司網(wǎng)站的網(wǎng)址等探越。
-
證書所使用的簽名算法(Signature algorithm)
這個數(shù)字證書的數(shù)字簽名所使用的加密算法,這樣就可以使用證書發(fā)布機構(gòu)的證書里面的公鑰窑业,根據(jù)這個算法對指紋進行解密钦幔。
-
證書發(fā)行者對證書的數(shù)字簽名(Thumbprint)
也就是該數(shù)字證書的指紋,用于保證數(shù)字證書的完整性常柄,確保證書沒有被修改過鲤氢。其原理就是在發(fā)布證書時,CA機構(gòu)會根據(jù)簽名算法(Signature algorithm)對整個證書計算其hash值(指紋)并和證書放在一起西潘,使用者打開證書時卷玉,自己也根據(jù)簽名算法計算一下證書的hash值(指紋),如 果和證書中記錄的指紋對的上秸架,就說明證書沒有被修改過揍庄。
可以看出,數(shù)字證書本身也用到了數(shù)字簽名技術(shù)东抹,只不過簽名的內(nèi)容是整個證書(里面包含了證書所有者的公鑰以及其他一些內(nèi)容)蚂子。與普通數(shù)字簽名不同的是,數(shù)字證書的簽名者不是隨隨便便一個普通機構(gòu)缭黔,而是 CA 機構(gòu)食茎。這就好像你的大學畢業(yè)證書上簽名的一般都是德高望重的校長一樣。一般來說馏谨,這些 CA 機構(gòu)的根證書已經(jīng)在設(shè)備出廠前預(yù)先安裝到了你的設(shè)備上了别渔。所以,數(shù)字證書可以保證證書里的公鑰確實是這個證書所有者的惧互,或者證書可以用來確認對方的身份哎媚。可見喊儡,數(shù)字證書主要是用來解決公鑰的安全發(fā)放問題拨与。
綜上所述,總結(jié)一下艾猜,數(shù)字簽名和簽名驗證的大體流程如下圖所示:
二买喧、APK Signature Scheme v1
2.1 簽名工具
Android 應(yīng)用的簽名工具有兩種:jarsigner
和 signAPK
。它們的簽名算法沒什么區(qū)別匆赃,主要是簽名使用的文件不同淤毛。
- jarsigner:jdk 自帶的簽名工具,可以對 jar 進行簽名算柳。使用 keystore 文件進行簽名低淡。生成的簽名文件默認使用 keystore 的別名命名。
- signAPK:Android sdk 提供的專門用于 Android 應(yīng)用的簽名工具。使用 pk8查牌、x509.pem 文件進行簽名事期。其中 pk8 是私鑰文件,x509.pem 是含有公鑰的文件纸颜。生成的簽名文件統(tǒng)一使用“CERT”命名。
既然這兩個工具都是給 APK 簽名的绎橘,那么 keystore 文件和 pk8胁孙,x509.pem 他們之間是不是有什么聯(lián)系呢?答案是肯定的称鳞,他們之間是可以轉(zhuǎn)化的涮较,這里就不再分析如何進行轉(zhuǎn)化,網(wǎng)上的例子很多冈止。
還有一個需要注意的知識點狂票,如果我們查看一個keystore 文件的內(nèi)容,會發(fā)現(xiàn)里面包含有一個 MD5 和 SHA1 摘要熙暴,這個就是 keystore 文件中私鑰的數(shù)據(jù)摘要闺属,這個信息也是我們在申請很多開發(fā)平臺賬號時需要填入的信息。
2.2 簽名過程
首先我們?nèi)我膺x取一個簽名后的 APK(Sample-release.APK)解壓:
[圖片上傳失敗...(image-ff566a-1603377806829)]
在 META-INF
文件夾下有三個文件:MANIFEST.MF
周霉、CERT.SF
掂器、CERT.RSA
。它們就是簽名過程中生成的文件俱箱,姑且叫他們“簽名三兄弟”吧国瓮,把它們搞清楚了,你就精通簽名了狞谱。
2.2.1 MANIFEST.MF
該文件中保存的內(nèi)容其實就是逐一遍歷 APK 中的所有條目乃摹,如果是目錄就跳過,如果是一個文件跟衅,就用 SHA1(或者 SHA256)消息摘要算法提取出該文件的摘要然后進行 BASE64 編碼后孵睬,作為“SHA1-Digest”屬性的值寫入到 MANIFEST.MF 文件中的一個塊中。該塊有一個“Name”屬性与斤, 其值就是該文件在 APK 包中的路徑肪康。
2.2.2 CERT.SF
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 編碼
對于 SHA1-Digest 值的驗證可以手動進行,將 MANIFEST.MF 中任意一個塊的內(nèi)容復制并保存在一個新的文檔中撩穿,注意文末需要加兩個換行(這是由 signAPK 的源碼決定的)
[圖片上傳失敗...(image-7de711-1603377806828)]
2.2.3 CERT.RSA
這里會把之前生成的 CERT.SF 文件磷支,用私鑰計算出簽名, 然后將簽名以及包含公鑰信息的數(shù)字證書一同寫入 CERT.RSA 中保存。這里要注意的是食寡,Android APK 中的 CERT.RSA 證書是自簽名的雾狈,并不需要這個證書是第三方權(quán)威機構(gòu)發(fā)布或者認證的,用戶可以在本地機器自行生成這個自簽名證書抵皱。Android 目前不對應(yīng)用證書進行 CA 認證善榛。
2.2.3.1 什么是自簽名證書辩蛋?
所謂自簽名證書是指自己給自己頒發(fā)的證書,即公鑰證書中 Issuer(發(fā)布者)和 Subject(所有者)是相同的移盆。當然悼院,APK 也可以采用由 CA 頒發(fā)私鑰證書進行簽名。采用非自簽名時咒循,最終 APK 的公鑰證書中就會包含證書鏈据途,并且會存在多余一個證書,證書間通過 Issuer 與 Subject進行關(guān)聯(lián)叙甸,Issuer 負責對 Subject 進行認證颖医。當安裝 APK 時,系統(tǒng)只會用位于證書鏈 中最底層的證書對 APK 進行校驗裆蒸,但并不會驗證證書鏈的有效性熔萧。
在 HTTPS 通信中使用自簽名證書時瀏覽器的顯示效果:
CERT.RSA 文件中的內(nèi)容:
這里我們看到的都是二進制文件,因為RSA文件加密了僚祷,所以我們需要用openssl命令才能查看其內(nèi)容:
$ openssl pkcs7 -inform DER -in /<文件存放路徑>/Sample-release_new/original/META-INF/CERT.RSA -text -noout -print_certs
[圖片上傳失敗...(image-61d7d0-1603377806828)]
綜上所述佛致,一個完整的簽名過程如下所示:
2.3 簽名校驗過程
簽名驗證是發(fā)生在APK的安裝過程中,一共分為三步:
檢查 APK 中包含的所有文件久妆,對應(yīng)的摘要值與 MANIFEST.MF 文件中記錄的值一致晌杰。
使用證書文件(RSA 文件)檢驗簽名文件(SF 文件)沒有被修改過。
使用簽名文件(SF 文件)檢驗 MF 文件沒有被修改過筷弦。
綜上所述肋演,一個完整的簽名驗證過程如下所示:
為什么使用這樣的簽名流程呢?
我們假設(shè)一下烂琴,首先爹殊,如果你改變了 APK 包中的任何文件,那么在 APK 安裝校驗時奸绷,改變后的文件摘要信息與 MANIFEST.MF 的檢驗信息不同梗夸,于是驗證失敗,程序就不能成功安裝号醉。
其次反症,如果你對更改過的文件相應(yīng)的算出新的摘要值,然后更改 MANIFEST.MF 文件里面對應(yīng)的屬性值畔派,那么必定與 CERT.SF 文件中算出的摘要值不一樣铅碍,照樣驗證失敗。
最后线椰,如果你還不死心胞谈,繼續(xù)計算 MANIFEST.MF 的摘要值,相應(yīng)的更改 CERT.SF 里面的值,那么數(shù)字簽名值必定與 CERT.RSA 文件中記錄的不一樣烦绳,還是失敗卿捎。
那么能不能繼續(xù)偽造數(shù)字簽名呢她混?不可能喘先,因為沒有數(shù)字證書對應(yīng)的私鑰。
三浑娜、APK Signature Scheme v2
APK 簽名方案 v2 是一種全文件簽名方案睹晒,該方案能夠發(fā)現(xiàn)對 APK 的受保護部分進行的所有更改趟庄,從而有助于加快驗證速度并增強完整性保證。
3.1 v1 簽名機制的劣勢
從 Android 7.0 開始伪很,Android 支持了一套全新的 V2 簽名機制,為什么要推出新的簽名機制呢奋单?通過前面的分析锉试,可以發(fā)現(xiàn) v1 簽名有兩個地方可以改進:
- 簽名校驗速度慢
校驗過程中需要對apk中所有文件進行摘要計算,在 APK 資源很多览濒、性能較差的機器上簽名校驗會花費較長時間呆盖,導致安裝速度慢。
- 完整性保障不夠
META-INF 目錄用來存放簽名贷笛,自然此目錄本身是不計入簽名校驗過程的应又,可以隨意在這個目錄中添加文件,比如一些快速批量打包方案就選擇在這個目錄中添加渠道文件乏苦。
為了解決這兩個問題株扛,在 Android 7.0 Nougat 中引入了全新的 APK Signature Scheme v2。
3.2 v2 帶來了什么變化汇荐?
由于在 v1 僅針對單個 ZIP 條目進行驗證洞就,因此,在 APK 簽署后可進行許多修改 — 可以移動甚至重新壓縮文件掀淘。事實上旬蟋,編譯過程中要用到的 ZIPalign 工具就是這么做的,它用于根據(jù)正確的字節(jié)限制調(diào)整 ZIP 條目革娄,以改進運行時性能倾贰。而且我們也可以利用這個東西,在打包之后修改 META-INF 目錄下面的內(nèi)容拦惋,或者修改 ZIP 的注釋來實現(xiàn)多渠道的打包匆浙,在 v1 簽名中都可以校驗通過。
v2 簽名將驗證歸檔中的所有字節(jié)架忌,而不是單個 ZIP 條目吞彤,因此,在簽署后無法再運行 ZIPalign(必須在簽名之前執(zhí)行)。正因如此饰恕,現(xiàn)在挠羔,在編譯過程中,Google 將壓縮埋嵌、調(diào)整和簽署合并成一步完成破加。
3.3 v2 簽名模式
簡單來說,v2 簽名模式在原先 APK 塊中增加了一個新的塊(簽名塊)雹嗦,新的塊存儲了簽名范舀,摘要,簽名算法了罪,證書鏈锭环,額外屬性等信息,這個塊有特定的格式泊藕,具體格式分析見后文辅辩,先看下現(xiàn)在 APK 成什么樣子了。
為了保護 APK 內(nèi)容娃圆,整個 APK(ZIP文件格式)被分為以下 4 個區(qū)塊:
- ZIP 條目的內(nèi)容(從偏移量 0 處開始一直到“APK 簽名分塊”的起始位置)
- APK 簽名分塊
- ZIP 中央目錄
- ZIP 中央目錄結(jié)尾
[圖片上傳失敗...(image-d32cc4-1603377806828)]
其中玫锋,應(yīng)用簽名方案的簽名信息會被保存在 區(qū)塊 2(APK Signing Block)中,而區(qū)塊 1(Contents of ZIP entries)讼呢、區(qū)塊 3(ZIP Central Directory)撩鹿、區(qū)塊 4(ZIP End of Central Directory)是受保護的,在簽名后任何對區(qū)塊 1悦屏、3节沦、4 的修改都逃不過新的應(yīng)用簽名方案的檢查。
3.4 簽名過程
從上面我們可以看到 v2 模式塊有點類似于我們 META-INF
文件夾下的信息內(nèi)容窜管。那么對于上述當中摘要的信息又是怎么計算出來的呢散劫。
首先,說一下 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 大小分割纽竣,分別計算這些分段的摘要墓贿,最后把這些分段的摘要在進行計算得到最終的摘要也就是 APK 的摘要茧泪。然后將 APK 的摘要 + 數(shù)字證書 + 其他屬性生成簽名數(shù)據(jù)寫入到 APK Signing Block 區(qū)塊。
3.5 簽名校驗過程
接下來我們來看v2簽名的校驗過程聋袋,整體大概流程如下圖所示:
[圖片上傳失敗...(image-edd544-1603377806828)]
其中 v2 簽名機制是在 Android 7.0 以及以上版本才支持队伟。因此對于 Android 7.0 以及以上版本,在安裝過程中幽勒,如果發(fā)現(xiàn)有 v2 簽名塊嗜侮,則必須走 v2 簽名機制,不能繞過啥容。否則降級走 v1 簽名機制锈颗。
v1 和 v2 簽名機制是可以同時存在的,其中對于 v1 和 v2 版本同時存在的時候咪惠,v1 版本的 META_INF 的 .SF
文件屬性當中有一個 X-Android-APK-Signed
屬性:
X-Android-APK-Signed: 2
因此如果想繞過 v2 走 v1 校驗是不行的击吱。
3.6 v2 對多渠道打包的影響
之前的渠道包生成方案是通過在 META-INF 目錄下添加空文件,用空文件的名稱來作為渠道的唯一標識遥昧。但在新的應(yīng)用簽名方案下 META-INF 已經(jīng)被列入了保護區(qū)了姨拥,向 META-INF 添加空文件的方案會對區(qū)塊 1、3渠鸽、4 都會有影響。
可以參考:美團解決方案柴罐。