淺談程序的數(shù)字簽名
理論基礎(chǔ)
數(shù)字簽名它是基于非對(duì)稱密鑰加密技術(shù)與數(shù)字摘要算法技術(shù)的應(yīng)用,它是一個(gè)包含電子文件信息以及發(fā)送者身份,并能夠鑒別發(fā)送者身份以及發(fā)送信息是否被篡改的一段數(shù)字串。
一段數(shù)字簽名數(shù)字串,它包含電子文件經(jīng)過Hash編碼后產(chǎn)生的數(shù)字摘要,即一個(gè)Hash函數(shù)值以及發(fā)送者的公鑰和私鑰三部分內(nèi)容。發(fā)送方通過私鑰加密后發(fā)送給接收方,接收方使用公鑰解密,通過對(duì)比解密后的Hash函數(shù)值確定數(shù)據(jù)電文是否被篡改。
數(shù)字簽名(又稱公鑰數(shù)字簽名)是只有信息的發(fā)送者才能產(chǎn)生的別人無法偽造的一段數(shù)字串,這段數(shù)字串同時(shí)也是對(duì)信息的發(fā)送者發(fā)送信息真實(shí)性的一個(gè)有效證明。
它是一種類似寫在紙上的普通的物理簽名,但是在使用了公鑰加密領(lǐng)域的技術(shù)來實(shí)現(xiàn)的,用于鑒別數(shù)字信息的方法。
(圖片來源網(wǎng)絡(luò))
數(shù)字簽名方案是一種以電子形式存儲(chǔ)消息簽名的方法。一個(gè)完整的數(shù)字簽名方案應(yīng)該由兩部分組成:簽名算法和驗(yàn)證算法。
(圖片來源于網(wǎng)絡(luò))
android數(shù)字簽名
在android的APP應(yīng)用程序安裝過程中,系統(tǒng)首先會(huì)檢驗(yàn)APP的簽名信息,如果發(fā)現(xiàn)簽名文件不存在或者校驗(yàn)簽名失敗,系統(tǒng)則會(huì)拒絕安裝,所以APP應(yīng)用程序在發(fā)布到市場(chǎng)之前一定要進(jìn)行簽名。
在OTA升級(jí)中也必須使用到數(shù)字簽名進(jìn)行校驗(yàn),在應(yīng)用版本迭代必須使用相同的證書簽名,不然會(huì)生成一個(gè)新的應(yīng)用,導(dǎo)致更新失敗。在更新過程中使用相同的證書簽名的應(yīng)用可以共享代碼和功能
App安裝過程中簽名檢驗(yàn)的流程:
1、檢查 APP中包含的所有文件,對(duì)應(yīng)的摘要值與 MANIFEST.MF 文件中記錄的值一致。
2、使用證書文件(RSA 文件)檢驗(yàn)簽名文件(SF文件)是否被修改過。
3、使用簽名文件(SF 文件)檢驗(yàn) MF 文件沒有被修改過。
(圖片來源網(wǎng)絡(luò))
CERT.RSA包含數(shù)字簽名以及開發(fā)者的數(shù)字證書。CERT.RSA里的數(shù)字簽名是指對(duì)CERT.SF的摘要采用私鑰加密后的數(shù)據(jù);
MANIFEST.MF文件中是APP中每個(gè)文件名稱和摘要SHA256;
CERT.SF則是對(duì)MANIFEST.MF的摘要。
android中的數(shù)字簽名有2個(gè)主要作用:
1、能定位消息確實(shí)是由發(fā)送方簽名并發(fā)出來的,其他假冒不了發(fā)送方的簽名。
2、確定消息的完整性,簽名它代表文件的特征,文件發(fā)生變化,數(shù)字簽名的數(shù)值也會(huì)發(fā)送變化。
Anroid中的簽名證書不需要權(quán)威機(jī)構(gòu)認(rèn)證,一般是開發(fā)者的自簽名證書。所以簽名信息中會(huì)包含有開發(fā)者信息,在一定程度上可以防止應(yīng)用被破解二次打包成山寨的APP應(yīng)用,所以簽名信息也是用于對(duì)APP包防二次打包的一個(gè)校驗(yàn)功能點(diǎn)。
(上圖是android studio中自創(chuàng)建簽名的界面)
在 Android Studio中通過上圖創(chuàng)建簽名信息后,最終會(huì)生成一個(gè) .jks 的文件,它是用作證書和私鑰的二進(jìn)制文件。
(上圖是反編譯工具直接查看app的簽名信息),也可以通過jarsigner,jadx,jeb等工具查看app的簽名信息。
從上圖中可以看到這個(gè)APP采用了V1和V2簽名信息,Android中的簽名目前主要由V1、V2、V3、V4組成的。
v1簽名方案:基于 JAR 簽名,簽名完之后是META-INF 目錄下的三個(gè)文件:MANIFEST.MF、CERT.SF、CERT.RSA。通過這三個(gè)文件校驗(yàn)來確保APP中的每個(gè)文件都不被改動(dòng)。
APK v1的缺點(diǎn)就是META-INF目錄下的文件并不在校驗(yàn)范圍內(nèi),所以之前多渠道打包等都是通過在這個(gè)目錄下添加文件來實(shí)現(xiàn)的。
V2簽名方案:它是在Android 7.0系統(tǒng)中引入,為了使 APP可以在 Android 6.0 (Marshmallow) 及更低版本的設(shè)備上安裝,應(yīng)先使用 JAR 簽名功能對(duì) APP 進(jìn)行簽名,然后再使用 v2 方案對(duì)其進(jìn)行簽名。它是一個(gè)全文件的簽名方案,它能夠發(fā)現(xiàn)對(duì) APP的受保護(hù)部分進(jìn)行的所有更改,從而有助于加快驗(yàn)證速度并增強(qiáng)完整性保證。
V2簽名,它會(huì)在 APP文件中插入一個(gè)APP簽名分塊,該分塊位于“ZIP 中央目錄”部分之前并緊鄰該部分。在“APP簽名分塊”內(nèi),v2 簽名和簽名者身份信息會(huì)存儲(chǔ)在 APK 簽名方案 v2 分塊中。
V3簽名方案:它是Android 9.0系統(tǒng)中引入,基于 v2簽名的升級(jí),Android 9 支持 APK密鑰輪替,這使應(yīng)用能夠在 APK 更新過程中更改其簽名密鑰。為了實(shí)現(xiàn)輪替,APK 必須指示新舊簽名密鑰之間的信任級(jí)別。v3 在 APK 簽名分塊中添加了有關(guān)受支持的 SDK 版本和 proof-of-rotation 結(jié)構(gòu)的信息。
下面鏈接官方對(duì)V3簽名相關(guān)的說明
https://source.android.google.cn/security/apksigning/v3
APK 密鑰輪替功能可以參考:
https://developer.android.google.cn/about/versions/pie/android-9.0
V4簽名方案:它是在Android 11.0 引入,用來支持 ADB 增量 APK 安裝。通過 APK 簽名方案 v4 支持與流式傳輸兼容的簽名方案。v4 簽名基于根據(jù) APK 的所有字節(jié)計(jì)算得出的 Merkle 哈希樹。
Android 11 將簽名存儲(chǔ)在單獨(dú)的 .apk.idsig 文件中。
下面2個(gè)鏈接是官方對(duì)V4簽名的相關(guān)說明
https://source.android.google.cn/security/apksigning/v4
https://developer.android.google.cn/about/versions/11/features
從上面的簽名信息截圖中,也可以看到android的簽名采用的是X.509V3國際標(biāo)準(zhǔn)。
這個(gè)標(biāo)準(zhǔn)下約定了簽名證書必須包含以下的內(nèi)容。
1、證書的序列號(hào)
2、證書所使用的簽名算法
3、證書的發(fā)行機(jī)構(gòu)名稱,命名規(guī)則一般采用X.500格式
4、證書的有效期
5、證書的所有人的名稱
6、證書所有人的公開密鑰
7、證書發(fā)行者對(duì)證書的簽名
從上圖APP的簽名信息中數(shù)字簽名要包含摘要加密算法:MD5、SHA-1、SHA-256
MD5是一種不可逆的加密算法。
SHA1:它是由NISTNSA設(shè)計(jì)為同DSA一起使用的,它對(duì)長度小于264的輸入,產(chǎn)生長度為160bit的散列值,因此抗窮舉(brute-force)性更好。
SHA-256 是 SHA-1 的升級(jí)版,現(xiàn)在 Android 簽名使用的默認(rèn)算法都已經(jīng)升級(jí)到 SHA-256 了。
摘要算法中又涉及到對(duì)稱加密和非對(duì)加密
對(duì)稱加密就是在加密和解密過程中需要使用同一個(gè)密鑰
非對(duì)稱加密使用公鑰/私鑰中的公鑰來加密明文,然后使用對(duì)應(yīng)的私鑰來解密密文。
APP中如果沒采用加固保護(hù),容易出現(xiàn)二次打包重新簽名的山寨APP。
APP中二次打包流程:破解者需要對(duì)APK文件做反編譯分析,反編譯為smali代碼,并對(duì)某些關(guān)鍵函數(shù)或者資源進(jìn)行修改,再回編譯為apk文件并重簽名。
常見的對(duì)抗二次打包的方案:
1、簽名校驗(yàn)
原理:二次打包會(huì)篡改簽名,通過簽名前后的變化可以檢測(cè)是否被二次打包;但是這種很容易被hook掉。
2、文件校驗(yàn)
原理:二次打包前后apk關(guān)鍵文件hash值比較,判斷是否被修改;但是這種很容易被hook掉。
3、核心函數(shù)轉(zhuǎn)為jni層實(shí)現(xiàn)
原理:java層代碼轉(zhuǎn)為jni層實(shí)現(xiàn),jni層代碼相對(duì)而言篡改難度更大;寫大量反射代碼降低了開發(fā)效率。
window數(shù)字簽名
Window的數(shù)字簽名是微軟的一種安全保障機(jī)制。
Window數(shù)字簽名中的簽名證書用于驗(yàn)證開發(fā)者身份真實(shí)性、保護(hù)代碼的完整性。用戶下載軟件時(shí),能通過數(shù)字簽名驗(yàn)證軟件來源可信,確認(rèn)軟件、代碼沒有被非法篡改或植入病毒。所以,軟件開發(fā)者會(huì)在軟件發(fā)行前使用代碼簽名證書為軟件代碼添加數(shù)字簽名。
對(duì)于一個(gè)Windows的可執(zhí)行應(yīng)用程序,簽發(fā)數(shù)字簽名的時(shí)候需要計(jì)算的數(shù)據(jù)摘要并不會(huì)是程序文件的全部數(shù)據(jù),而是要排除一些特定區(qū)域的數(shù)據(jù)。而這些區(qū)域當(dāng)然和PE文件結(jié)構(gòu)有關(guān),具體地,不管是簽發(fā)時(shí)還是校驗(yàn)時(shí)計(jì)算的hash都會(huì)排除一個(gè)checksum字段、一個(gè)Security數(shù)據(jù)目錄字段以及數(shù)字簽名證書部分的數(shù)據(jù)。
Window簽名的RSA算法:通過公鑰與私鑰來判斷私鑰的合法。
公鑰與私鑰具有對(duì)稱性,既可以通過私鑰加密,公鑰解密,以此來論證私鑰持有者的合法身份。也可以通過公鑰加密,私鑰解密,來對(duì)私鑰持有者發(fā)信息而不被泄露。
由于在交換公鑰時(shí)免不了遭遇中間人劫持,因此window程序的簽名證書,都需要第三方權(quán)威機(jī)構(gòu)的認(rèn)證,并不像android程序一樣開發(fā)者可以對(duì)自己程序簽發(fā)證書。
(查看某程序的數(shù)字簽名信息)
從上面截圖中看到了摘要算法用到sha1和sha256。
由于SHA-256更強(qiáng)的安全性,現(xiàn)在SHA-256已經(jīng)作為代碼簽名證書的行業(yè)標(biāo)準(zhǔn)簽名算法。
從上圖中看到程序擁有2個(gè)簽名信息,也就是雙簽名機(jī)制。
雙簽名就是對(duì)一個(gè)軟件做兩次簽名,先進(jìn)行SHA1簽名,之后再進(jìn)行SHA2簽名的做法就叫做雙簽名。雙簽名需要一張支持SHA1和SHA2算法的代碼簽名證書,利用具備雙簽名功能的工具導(dǎo)入申請(qǐng)的代碼簽名證書對(duì)軟件或應(yīng)用程序進(jìn)行雙簽名,簽發(fā)后的軟件或應(yīng)用程序就支持SHA1和SHA2簽名算法。
Windows10要求使用SHA2算法簽名,而Windows7(未更新補(bǔ)丁的)因其兼容性只能使用SHA1算法簽名,那么使用一張支持雙簽SHA1和SHA2算法的代碼簽名證書就可以實(shí)現(xiàn)。
軟件簽名校驗(yàn)的流程圖
(上圖來源網(wǎng)絡(luò))
Windows系統(tǒng)驗(yàn)證簽名流程
1、系統(tǒng)UAC功能開啟(用戶賬戶控制功能,默認(rèn)開啟);
2、程序啟動(dòng)時(shí),進(jìn)行CA校驗(yàn)程序簽名信息;
2.1、使用同樣算法對(duì)軟件產(chǎn)生Hash表
2.2、使用公鑰產(chǎn)生一個(gè)Hash表認(rèn)證摘要
2.3、比較程序的Hash表認(rèn)證摘要 與 自己生成的Hash表認(rèn)證摘要是否一致。
3、程序在window系統(tǒng)執(zhí)行功能。
數(shù)字簽名的驗(yàn)證過程本質(zhì):
1、通過對(duì)要驗(yàn)證的軟件創(chuàng)建hash數(shù)據(jù);
2、使用發(fā)布者的公共密匙來解密被加密的hash數(shù)據(jù);
3、最后比較解密的hash和新獲得的hash,如果匹配說明簽名是正確的,軟件沒有被修改過。
代碼實(shí)現(xiàn)校驗(yàn)程序是否有簽名,它本質(zhì)上就是被加密的hash和發(fā)布者的數(shù)字證書被插入到要簽名的軟件,最后在進(jìn)行校驗(yàn)簽名信息。
(實(shí)現(xiàn)判斷程序是否有簽名功能)
代碼實(shí)現(xiàn)可以通過映射文件方式,然后去安裝PE文件結(jié)構(gòu)去讀取,讀取到可選頭中的數(shù)據(jù)目錄表,通過判斷數(shù)據(jù)目錄表中
的IMAGE_DIRECTORY_ENTRY_SECURITY的虛擬地址和大小不為空,那么就表示改應(yīng)用程序有簽名,因?yàn)閿?shù)據(jù)簽名都是存在在這個(gè)字段中。
同樣如果要將某個(gè)應(yīng)用程序的簽名信息給抹除了,也是一樣的思路,將數(shù)據(jù)目錄表中的IMAGE_DIRECTORY_ENTRY_SECURITY的大小和地址都設(shè)置為0即可。
下圖通過PE工具,可以查看這個(gè)字段Security的虛擬地址和大小不為空那么表示應(yīng)用程序經(jīng)過簽名的。
小結(jié)
數(shù)字簽名不管是在android端還是window端,它都是一種應(yīng)用程序的身份標(biāo)志,在安全領(lǐng)域中對(duì)應(yīng)用程序的數(shù)字簽名校驗(yàn)是一個(gè)很常見的鑒別真?zhèn)蔚囊粋€(gè)手段。
現(xiàn)在很多殺毒的廠商也都是通過這個(gè)數(shù)字簽名維度,作為一個(gè)該應(yīng)用程序是否可信程序的校驗(yàn),雖然一些安全殺毒廠商簽完名后還是誤報(bào)毒,那這只能找廠商開白名單了。
作者:小道安全
歡迎關(guān)注微信公眾號(hào) :小道安全