您現在的位置是:首頁 > 足球

Android10.0應用安裝白名單——添加簽名校驗

  • 由 Android系統實戰開發 發表于 足球
  • 2021-12-02
簡介MF檔案的內容進行SHA1計算,然後進行編碼,將該值寫到SHA1-Digest-Manifest中:1SHA1-Digest-Manifest: iaeBE2KJWElTbmMNGnjxretMvz8=這裡對MANIFEST

vivo怎麼新增應用白名單

背景

為了避免系統被安裝上各種各樣的app,客戶要求系統需要有個安裝白名單的功能。

思路

白名單功能主要是透過確認要安裝的應用是否在白名單上,如果不在,則不允許安裝。篩選的標準可以透過包名進行判斷。但單純包名進行判斷還是不夠安全,這裡是想再加個簽名校驗的機制,畢竟每個簽名都是獨一無二的。

這個過程,主要難點在於如何獲取各個apk簽名。在說明如何在程式碼中獲取到系統簽名之前,先大概說下Android應用的簽名機制。

Android應用簽名

簽名的基本目的就是不允許apk內部任意一個檔案的內容被篡改。所以得保證每個檔案都被加密到。

將任意一個簽過名的apk進行解壓,都可以發現一個叫META-INF的資料夾,該資料夾包括但不限於如下三個檔案:

1CERT。RSACERT。SFMANIFEST。MF

1。MANIFEST。MF檔案。對APK包中每個檔案(資料夾和簽名檔案除外)進行遍歷,使用SHA1或者SHA256生成摘要資訊。然後再用base64進行編碼,擷取MANIFEST。MF檔案中某一段:

1Name: AndroidManifest。xml

2SHA1-Digest: D2yOY7wstlBC3AbjQznUDa6/8Xw=

這裡我們可以自己對AndroidManifest。xml這個檔案透過SHA1生成摘要資訊,有線上的SHA1:

1http://www。metools。info/code/c92。html

Android10.0應用安裝白名單——添加簽名校驗

image

拿到摘要後,可以透過線上base64編碼,將此摘要進行編碼:

1http://tomeko。net/online_tools/hex_to_base64。php?lang=en

Android10.0應用安裝白名單——添加簽名校驗

image

可以看到這裡獲取到的base64編碼結果跟MANIFEST。MF檔案描述的一樣。

其餘檔案的base64編碼也是如此計算得來。從這裡就知道,如果apk中的檔案被篡改了,則最終得到的base64編碼跟MANIFEST。MF檔案描述不一樣,就會導致安裝出錯。當然,也可以手動計算出所修改檔案的base64編碼,然後更新到MANIFEST。MF檔案中,但也會功虧一簣,因為還有CERT。RSA和CERT。SF。

2。CERT。SF檔案。擷取部分該檔案:

1Signature-Version: 1。0

2SHA1-Digest-Manifest: iaeBE2KJWElTbmMNGnjxretMvz8=

3Created-By: 1。0 (Android SignApk)

4

5Name: kotlin/collections/MapWithDefault。kotlin_metadata

6SHA1-Digest: je8WuIzQjM5yX2bkDmjjyviMxOE=

7

8Name: kotlin/coroutines/intrinsics/CoroutinesIntrinsicsHKt。kotlin_meta

9 data

10SHA1-Digest: reRpbwjfyR7tladgIdLzjpREduA=

11

12Name: res/interpolator/btn_checkbox_checked_mtrl_animation_interpolato

13 r_0。xml

14SHA1-Digest: 9Lo7vzAcNsmM/qCg9/iamygexzk=

這個檔案是對MANIFEST。MF檔案中的每一項再做一次SHA1計算,然後再進行base64編碼。另外還對MANIFEST。MF檔案的內容進行SHA1計算,然後進行編碼,將該值寫到SHA1-Digest-Manifest中:

1SHA1-Digest-Manifest: iaeBE2KJWElTbmMNGnjxretMvz8=

這裡對MANIFEST。MF檔案進行了一層篡改保護,只要MANIFEST。MF檔案被修改過,那最後得到的base64編碼肯定對不上。當然,到此為止,如果只是做到這一步,那還是可以被篡改的。關鍵看看CERT。RSA檔案。

3。CERT。RSA檔案。該檔案儲存了公鑰,所採用的加密演算法等資訊。還有比較重要的是,對CERT。SF檔案的內容用私鑰進行加密之後的值。也就是說,即使手動篡改了MANIFEST。MF檔案和CERT。SF檔案,CERT。RSA檔案還是會對應不上,安裝就會失敗。

apk安裝白名單進行簽名校驗

上面所說是簽名的過程,而安裝則是反過來。

CERT。RSA這個檔案中的包含的公鑰對數字簽名(自己本身)進行解密,將解密後的結果與CERT。SF檔案hash運算後的結果進行比對,一致的話就返回證書鏈資訊,並將證書鏈儲存在certificates物件中,同時說明CERT。SF檔案沒有被篡改。如果這裡對比透過,則下一步就驗證MANIFEST。MF是否被篡改。在這一步,會遍歷每個檔案(entry),對非資料夾非簽名檔案的檔案,逐個生成SHA1的數字簽名信息,再用Base64進行編碼,並與MANIFEST。MF中對內容進行比對,若一一對應,則表示檔案沒被篡改。到這裡校驗APK所有檔案是否有被篡改,也已完成。

顯然,如果我們想要在安裝白名單上實現簽名校驗,那可以對比RSA檔案上的證書籤名是否與apk的簽名一致即可。

獲取apk簽名的證書指紋

拿到app後,透過解壓apk,獲取到CERT。RSA檔案,執行如下指令:

1keytool-printcert-fileCERT。RSA

會可以得到簽名的證書指紋:

1Certificatefingerprints:

2MD5: 0E:BA:50:A4:5C:15:B3:5D:97:7D:04:D8:43:79:B3:58

3SHA1: 41:79:1C:9B:8F:AF:15:E1:AC:D5:AA:F5:92:10:FD:42:46:7D:82:70

4SHA256: 2D:37:0C:21:F5:DF:D5:53:D2:A7:96:31:4B:70:92:5F:B3:8A:DE:EF:90:86:4C:92:0B:BB:BB:12:88:7D:35:20

每個簽名的證書指紋都是唯一的,如此一來,就可以透過該證書指紋的唯一性來進行簽名校驗了。

android原始碼中獲取證書指紋

要想獲取apk的簽名證書指紋,就需要先獲取其簽名。app安裝時透過PackageParser類來解析安裝包的資訊,而簽名也包含其中。我們可以利用這個來獲取到簽名的證書指紋。具體的安裝流程這裡不多介紹,直接定位到PackageManagerService類的preparePackageLI方法,該方法會去new出一個PackageParser物件來做apk包的解析:

1private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)

2throws PrepareFailure {

3

4 。。。

5 PackageParser pp = new PackageParser();

6 pp。setSeparateProcesses(mSeparateProcesses);

7 pp。setDisplayMetrics(mMetrics);

8 pp。setCallback(mPackageParserCallback);

9

10 Trace。traceBegin(TRACE_TAG_PACKAGE_MANAGER, “parsePackage”);

11final PackageParser。Package pkg;

12try {

13 pkg = pp。parsePackage(tmpPackageFile, parseFlags);

14 DexMetadataHelper。validatePackageDexMetadata(pkg);

15 } catch (PackageParserException e) {

16thrownew PrepareFailure(“Failed parse during installPackageLI”, e);

17 } finally {

18 Trace。traceEnd(TRACE_TAG_PACKAGE_MANAGER);

19 }

20 。。。

21

22try {

23// either use what we‘ve been given or parse directly from the APK

24if (args。signingDetails != PackageParser。SigningDetails。UNKNOWN) {

25 pkg。setSigningDetails(args。signingDetails);

26 } else {

27 PackageParser。collectCertificates(pkg, false/* skipVerify */);

28 }

29 } catch (PackageParserException e) {

30thrownew PrepareFailure(“Failed collect during installPackageLI”, e);

31 }

32 。。。

33}

這裡列出部分程式碼,pkg是一個Pakage物件,屬於PackageParser內部類,該類用於儲存apk相關的資訊,如包名,apk路徑,簽名等。

簽名拿到後,就可以拿到它的證書指紋了,如下:

1String sha1 = getFingerprint(pkg。mSigningDetails。signatures[0], “SHA1”);

2

3private String getFingerprint(Signature signature, String hashAlgorithm) {

4if (signature == null) {

5returnnull;

6 }

7try {

8 MessageDigest digest = MessageDigest。getInstance(hashAlgorithm);

9return toHexadecimalString(digest。digest(signature。toByteArray()));

10 } catch(NoSuchAlgorithmException e) {

11// ignore

12 }

13returnnull;

14}

MessageDigest 類為應用程式提供資訊摘要演算法的功能,如 MD5 或 SHA 演算法。資訊摘要是安全的單向雜湊函式,它接收任意大小的資料,並輸出固定長度的雜湊值。

這裡是根據SHA演算法獲取摘要,即證書指紋。

簽名校驗

用該指紋和使用keytool得出的SHA1值進行比對,如果符合,則簽名校驗透過,允許應用安裝。具體實現也比較簡單,可以將keytool得出的SHA1值儲存到白名單中,然後在apk安裝過程中,再讀出進行比對即可。

結語

每個簽名的證書指紋,即訊息摘要,是哪些內容經過SHA1、MD5、SHA256演算法得到的呢?私鑰加上其他的一些內容?

Top