Android 安全的其它話題

在本章中,我們會涉及到與 Android 安全相關的其他主題,這些主題不直接屬于已經涉及的任何主題。

6.1 Android 簽名過程

Android 應用程序以 Android 應用包文件(.apk文件)的形式分發到設備上。 由于這個平臺的程序主要是用 Java 編寫的,所以這種格式與 Java 包的格式 -- jar(Java Archive)有很多共同點,它用于將代碼,資源和元數據(來自可選的META-INF目錄 )文件使用 zip 歸檔算法轉換成一個文件。 META-INF目錄存儲軟件包和擴展配置數據,包括安全性,版本控制,擴展和服務[5]。 基本上,在 Android 的情況中,apkbuilder工具將構建的項目文件壓縮到一起[1],使用標準的 Java 工具jarsigner對這個歸檔文件簽名[6]。 在應用程序簽名過程中,jarsigner創建META-INF目錄,在 Android 中通常包含以下文件:清單文件(MANIFEST.MF),簽名文件(擴展名為.SF)和簽名塊文件(.RSA.DSA) 。

清單文件(MANIFEST.MF)由主屬性部分和每個條目屬性組成,每個包含在未簽名的apk中文件擁有一個條目。 這些每個條目中的屬性存儲文件名稱信息,以及使用 base64 格式編碼的文件內容摘要。 在 Android 上,SHA1 算法用于計算摘要。 清單 6.1 中提供了清單文件的摘錄。

1 Manifest?Version : 1.0 
2 Created?By: 1.6.0 41 (Sun Microsystems Inc. ) 
3 
4 Name: res/layout/main . xml 
5 SHA1?Digest : NJ1YLN3mBEKTPibVXbFO8eRCAr8= 
6 
7 Name: AndroidManifest . xml 
8 SHA1?Digest : wBoSXxhOQ2LR/pJY7Bczu1sWLy4=

代碼 6.1:清單文件的摘錄

包含被簽名數據的簽名文件(.SF)的內容類似于MANIFEST.MF的內容。 這個文件的一個例子如清單 6.2 所示。 主要部分包含清單文件的主要屬性的摘要(SHA1-Digest-Manifest-Main-Attributes)和內容摘要(SHA1-Digest-Manifest)。 每個條目包含清單文件中的條目的摘要以及相應的文件名。

 1 Signature?Version : 1.0 
 2 SHA1?Digest?Manifest?Main?Attributes : nl/DtR972nRpjey6ocvNKvmjvw8= 
 3 Created?By: 1.6.0 41 (Sun Microsystems Inc. ) 
 4 SHA1?Digest?Manifest : Ej5guqx3DYaOLOm3Kh89ddgEJW4= 
 5 
 6 Name: res/layout/main.xml 
 7 SHA1?Digest : Z871jZHrhRKHDaGf2K4p4fKgztk= 
 8 
 9 Name: AndroidManifest.xml 
10 SHA1?Digest : hQtlGk+tKFLSXufjNaTwd9qd4Cw= 
11 ...

代碼 6.2:簽名文件的摘錄

最后一部分是簽名塊文件(.DSA.RSA)。 這個二進制文件包含簽名文件的簽名版本; 它與相應的.SF文件具有相同的名稱。 根據所使用的算法(RSA 或 DSA),它有不同的擴展名。

相同的apk文件有可能簽署幾個不同的證書。 在這種情況下,在META-INF目錄中將有幾個.SF.DSA.RSA文件(它們的數量將等于應用程序簽名的次數)。

6.1.1 Android 中的應用簽名檢查

大多數 Android 應用程序都使用開發人員簽名的證書(注意 Android 的“證書”和“簽名”可以互換使用)。 此證書用于確保原始應用程序的代碼及其更新來自同一位置,并在同一開發人員的應用程序之間建立信任關系。 為了執行這個檢查,Android 只是比較證書的二進制表示,它用于簽署一個應用程序及其更新(第一種情況)和協作應用程序(第二種情況)。

這種對證書的檢查通過PackageManagerService中的方法int compareSignatures(Signature[] s1,Signature[] s2)來實現,代碼如清單 6.3 所示。在上一節中,我們注意到在 Android 中,可以使用多個不同的證書簽署相同的應用程序。這解釋了為什么該方法使用兩個簽名數組作為參數。盡管該方法在 Android 安全規定中占有重要地位,但其行為強烈依賴于平臺的版本。在較新版本中(從 Android 2.2 開始),此方法比較兩個Signature數組,如果兩個數組不等于null,并且如果所有s2簽名都包含在s1中,則返回SIGNATURE MATCH值,否則為SIGNATURE_NOT_MATCH。在版本 2.2 之前,此方法檢查數組s1是否包含在s2中。這種行為允許系統安裝升級,即使它們已經使用原始應用程序的證書子集簽名[2]。

在幾種情況下,需要同一開發人員的應用程序之間的信任關系。 第一種情況與signaturesignatureOrSystem的權限相關。 要使用受這些權限保護的功能,聲明權限和請求它的包必須使用同一組證書簽名。 第二種情況與 Android 運行具有相同 UID 或甚至在相同 Linux 進程中運行不同應用程序的能力有關。 在這種情況下,請求此類行為的應用程序必須使用相同的簽名進行簽名。

 1 static int compareSignatures ( Signature[] s1 , Signature[] s2 ) { 
 2   if ( s1 == null ) { 
 3     return s2 == null 
 4       ? PackageManager.SIGNATURE_NEITHER_SIGNED 
 5       : PackageManager.SIGNATURE_FIRST_NOT_SIGNED; 
 6   } 
 7   if ( s2 == null ) { 
 8     return PackageManager.SIGNATURE_SECOND_NOT_SIGNED; 
 9   } 
10   HashSet<Signature> set1 = new HashSet<Signature>() ; 
11   for ( Signature sig : s1 ) { 
12     set1.add( sig ) ; 
13   } 
14   HashSet<Signature> set2 = new HashSet<Signature>() ; 
15   for ( Signature sig : s2 ) { 
16     set2.add( sig ) ; 
17   } 
18   // Make sure s2 contains all signatures in s1 . 
19   if ( set1.equals ( set2 ) ) { 
20     return PackageManager.SIGNATURE_MATCH; 
21   } 
22   return PackageManager.SIGNATURE_NO_MATCH; 
23 }

代碼 6.3:PackageManagerService中的compareSignatures方法



25选5玩法中奖