軟體測試 | 應用程式簽名機制實現的原始碼分析

霍格沃茲測試 發佈 2023-12-24T08:09:16.406203+00:00

Android 採用簽名機制來保護應用程式的安全,以便於開發者進行身份鑑別,防止替換應用程式包和篡改內容。同時有助於在應用程式之間建立一種信任,可以由同一個私鑰簽名的若干個應用程式共享代碼和數據。Android 系統簽名主要有 ROM 簽名和應用程式 APk 簽名兩種形式。

Android 採用簽名機制來保護應用程式的安全,以便於開發者進行身份鑑別,防止替換應用程式包和篡改內容。同時有助於在應用程式之間建立一種信任,可以由同一個私鑰簽名的若干個應用程式共享代碼和數據。

Android 系統簽名主要有 ROM 簽名和應用程式 APk 簽名兩種形式。ROM 簽名是針對已經生成的 Android 系統 ROM 包進行簽名。應用程式 APK 簽名是針對開發者開發的應用程式安裝包 APK 進行簽名。前者是對整個 Android 系統包簽名,後者只對 Android 系統中一個應用程式 APK 簽名。這裡僅對 APK 簽名的執行過程進行代碼層面的分析,流程如圖所示。

Android 應用程式 APK 是 jar 包,簽名採用的工具是 signapk.jar 包,對應用程式安裝包簽名的執行命令如下:

Java -jar signapk.jar publickey privatekey input.apk output.apk

複製代碼

此命令實現了對應用程式安裝包 input.apk 簽名的功能。在 signapk.jar 命令中,第一個參數為公鑰 publickey,第二個參數為私鑰 privatekey,第三個參數為輸入的報名,第四個參數簽名後生成的輸入包名。在此命令中,signapk.jar 使用公鑰 publickey 和私鑰 privatekey 對 input.apk 安裝包進行簽名,生成 output.apk 包。signapk 源碼位於 build/tools/signapk/SignApk.java 中。

完成簽名後 APK 包中多了一個 META-INF 文件夾,其中有名為 MANIFEST.MF、CERT.SF 和 CERT.RSA 的三個文件。MANIFEST.MF 文件中包含很多 APK 包信息,如 manifest 文件版本、簽名版本、應用程式相關屬性、簽名相關屬性等。CERT.SF 是明文的簽名證書,通過採用私鑰進行簽名得到。CERT.RST 是密文的簽名證書,通過公鑰生成的。MANIFEST.MF、CERT.SF 和 CERT.RSA 三個文件所使用的公鑰和私鑰的生成可以通過 development/tools/make_key 來獲得。下面分被介紹 MANIFEST.MF、CERT.SR 和 CERT.RSA 三個文件生成方法。

(1)生成 MANIFEST.MF 文件

生成 MANIFEST.MF 是對 APK 包中所有未簽名文件逐個用算法 SHA1 進行數字簽名,再對數字簽名信息採用 Base64 進行編碼,最後將編完碼的簽名寫 MANIFEST.MFWEN 文件中。添加數字簽名到 manifest 文件通過調用 addDigestsToManifest 方法實現,具體代碼如下:

private static Manifest addDigestsToManifest(JarFile jar)
{
  ......
//遍歷update.apk包中所有文件
//得到簽名文件內容
InputStream data = jar.getInputStream(entry);


//更新文件內容
while ((num = data.read(buffer))>0 ) {
       md.undate(buffer,0,num);
}
.....
//進行SHA1簽名,並採用Base64進行編碼
attr.putValue("SHA1-Digest",base64.encode(md.digest()));
output.getEntries().put(name,attr);
....
}

複製代碼

需要說明,生成 MANIFEST.MF 使用 SHA1 算法進行數字簽名,SHA1 是一種 Hash 算法,兩個不同的信息經 Hash 運算後不回產生同樣的信息摘要,由於 SHA1 是單向的,所以不可能從消息摘要中復原原文。如果惡意程序改變了 APK 包中的文件,那麼在進行 APK 安裝校驗時,改變後的摘要信息與 MANIFEST.MF 的檢驗信息不同,應用程式便不能安裝成功。

(2)生成 CETR.SF 文件

在生成 MANIFEST.MF 文件之後,用 SHA1-RSA 算法對其進行私鑰簽名,便生成 CERT.SF。具體代碼如下:

Signature signature = Signature.getIntance("SHA1withRSA");
signature。initSign(privateKey);
je = new JarEntry(CERT_SF_NAME);
je.setTime(timestamp);
outputJar.putNextEntry(je);
wrireSignatureFile(manifest,newSignatureOutputStream(outputJar,signature));

複製代碼

RSA 是目前最有影響力的公鑰加密算法,是一種非對稱加密算法、能夠同時用於加密和數字簽字。由於 RAS 是對非對稱加密算法,因此用私鑰對生成 MANIFEST.MF 的數字簽名加密後,在 APK 安裝時只能使用公鑰才能解密它。

(3)生成 CERT.RSA 文件

生成 CERT.RSA 文件與生成 CERT.SF 文件不同之處在於,生成 CERT.RSA 文件使用了公鑰文件。CERT.RSA 文件中保存了公鑰以及所用的採用加密算法等信息。具體代碼如下:

js = new JarEntry(CERT_RSA_NAME);
je.setTime(timetamp);
outputJar.putNextEntry(je);
writeSignatureBlock(signature,publickey,outputJar);

複製代碼

通過以上對 Android 應用程式簽名的代碼分析,可以看出 Android 系統通過對第三方 APK 包進行簽名,達到保護系統安全的目的。應用程式簽名只要用於對開發者身份進行識別,達到防範惡意攻擊的目的,但不能有效地限制應用程式被惡意修改,只能夠檢測應用程式是否被修改過,如果應用程式被修改應該再採取相應的應對措施。

搜索微信公眾號:霍格沃茲測試學院

關鍵字: