Android 簽名機制
1、如何對APK簽名
(1)、建立數位憑證,android123.keystore
keytool -genkey -alias android123.keystore -keyalg RSA -validity 20000 -keystore android123.keystore
keytool工具是Java JDK內建的認證工具
-genkey參數表示:要產生一個認證(著作權、身份識別的安全性憑證)
-alias參數表示:認證有別名,-alias android123.keystore表示認證別名為android123.keystore
-keyalg RSA表示加密類型,RSA表示需要加密,以防止別人盜取
-validity 20000表示有效時間20000天
-keystore android123.keystore表示要產生的認證名稱為android123.keystore
Enter key password for
(RETURN if same as keystore password):此時按斷行符號
產生的數位憑證android123.keystore裡麵包換了非對稱式加密的私密金鑰、公開金鑰和認證。
(2)、使用數位憑證進行簽名
jarsigner -verbose -keystore android123.keystore -signedjar test_signed.apk test.apk android123.keystore
jarsigner是Java的簽名工具
-verbose參數表示:顯示出簽名詳細資料
-keystore表示使用目前的目錄中的android123.keystore簽署憑證檔案。
-signedjar test_signed.apk表示簽名後產生的APK名稱,test.apk表示未簽名的APK Android軟體, android.keystore表示別名
(3)、簽名後產生了META-INT檔案夾,裡麵包含的檔案如下:
通過這三個檔案,我們瞭解下第二步中jarsigner都做了什麼事情,我們先看MANIFEST.MF,如下:
Manifest-Version: 1.0Created-By: 1.0 (Android)Name: res/raw/aes.luaSHA1-Digest: M2O7Kjh31bRSTSaX9Kxeg9+r8t0=Name: AndroidManifest.xmlSHA1-Digest: gJSLROnRQjVNfuSf9ZLQ/jcfjCQ=Name: lib/armeabi-v7a/libuencrypt.soSHA1-Digest: 60nq3GlIOFjA2qQwpD0GHF0B+fs=Name: assets/aes.luaSHA1-Digest: M2O7Kjh31bRSTSaX9Kxeg9+r8t0=Name: res/drawable-hdpi-v4/ic_launcher.pngSHA1-Digest: Nq8q3HeTluE5JNCBpVvNy3BXtJI=Name: res/layout/activity_main.xmlSHA1-Digest: 29xFOv25tmFws/fZywW1pnKb0/0=Name: res/layout/lv_item.xmlSHA1-Digest: n+ABu8eXc8sgsr/koDg/u1UIHsk=Name: res/drawable-mdpi-v4/ic_launcher.pngSHA1-Digest: RRxOSvpmhVfCwiprVV/wZlaqQpw=Name: res/menu/main.xmlSHA1-Digest: FwPQ14VCI33UrtPR12pUamCNBtI=Name: lib/armeabi-v7a/libalgms.soSHA1-Digest: l6EtvZsMbYZLCRF/ym+gDCbb66A=Name: res/layout/gv_item.xmlSHA1-Digest: zJG1Od3RKnHgvtNspfJoL3Gjl9c=Name: res/drawable-xhdpi-v4/ic_launcher.pngSHA1-Digest: AfPh3OJoypH966MludSW6f1RHg4=Name: lib/armeabi/libluajava.soSHA1-Digest: hEXHJ2RO/N4HG7HpkvNLpwkezx8=Name: resources.arscSHA1-Digest: xvke7fWkq3vTndO6GxJygC191Io=Name: lib/armeabi-v7a/libluajava.soSHA1-Digest: G1oHj8pHfhE6cTmiIIyLf7q3g5I=Name: res/layout/notify.xmlSHA1-Digest: cwi7OQR/TBBCikvfrG1mWb/7aQ8=Name: classes.dexSHA1-Digest: ZFp/aGRiQlOrGaeCybupky6xL9w=Name: res/drawable-xxhdpi-v4/ic_launcher.pngSHA1-Digest: GVIfdEOBv4gEny2T1jDhGGsZOBo=Name: lib/armeabi/libalgms.soSHA1-Digest: sThUrFV9sUiv9GDot0L92RkYBPs=Name: lib/armeabi/libuencrypt.soSHA1-Digest: 60nq3GlIOFjA2qQwpD0GHF0B+fs=
裡麵包含了所有apk中資源分別求Hash值。
我們再看CERT.SF,如下:
Signature-Version: 1.0SHA1-Digest-Manifest: rpk81cwms7B69LRe8+DWDOXsXh4=Created-By: 1.0 (Android)Name: res/raw/aes.luaSHA1-Digest: 328J86FdzrMHCGbJ9zgSIL66Vhg=Name: AndroidManifest.xmlSHA1-Digest: 5FgYlUZJI5rg9CliE7aY0lJvQeA=Name: lib/armeabi-v7a/libuencrypt.soSHA1-Digest: c4LKMukodajHJes+c40iIKVR5Mc=Name: assets/aes.luaSHA1-Digest: bxsaWYSVcIxoulpdWPfY0BV2PiQ=Name: res/drawable-hdpi-v4/ic_launcher.pngSHA1-Digest: nVLQ/wUjf9D4KSB2I7WqoHR14JY=Name: res/layout/activity_main.xmlSHA1-Digest: JW6OyAas5Wk9A3gkVFXQfnW5/xM=Name: res/layout/lv_item.xmlSHA1-Digest: dNWFJFprP0T6rcGEzItXC7wCYkM=Name: res/drawable-mdpi-v4/ic_launcher.pngSHA1-Digest: NBFXy1maYHW4TAiVCw6R9+EBNqI=Name: res/menu/main.xmlSHA1-Digest: OKnRLZ88PSIyuOBi7mLTP2st5qo=Name: lib/armeabi-v7a/libalgms.soSHA1-Digest: FtY/V2plAUjgAuML1e13WkbAlv4=Name: res/layout/gv_item.xmlSHA1-Digest: dkF+JesLgH0dGCDQ3n8xB5x27/c=Name: res/drawable-xhdpi-v4/ic_launcher.pngSHA1-Digest: qLB+xSuTsdod1eS2aPJel/A5PvE=Name: lib/armeabi/libluajava.soSHA1-Digest: s4qgp8flPTMEZkF8z5QutBgFxrM=Name: resources.arscSHA1-Digest: 541ycGJWJPTgwVyrgsxvB8pjjCM=Name: lib/armeabi-v7a/libluajava.soSHA1-Digest: Ef0wS9E2VVNlCobz+Rfus6H98sQ=Name: res/layout/notify.xmlSHA1-Digest: ioOWjUP2Gg9EEwhuElzwisdCR6I=Name: classes.dexSHA1-Digest: K7z+duqJFBCe/hMgJWJQrzmLwxE=Name: res/drawable-xxhdpi-v4/ic_launcher.pngSHA1-Digest: W7nSszMeL1x0eIt3K2CoCIHU6Qg=Name: lib/armeabi/libalgms.soSHA1-Digest: +F1sBBeuDvU3e9uqpFyvdOSdQAE=Name: lib/armeabi/libuencrypt.soSHA1-Digest: JToW2wKlog94dVZeNv3cGOC3CwA=
首先對MANIFEST.MF整個檔案求Hash值存放在SHA1-Digest-Manifest中,然後再對MANIFEST.MF裡面的Hash值再求Hash值。
最後我們再來看,CERT.RSA,它是個二進位檔案。只能通過特定的工具讀出來其中的內容。可參考從CERT.RSA中提取認證一文。
讀出來的內容如下,參考Android簽名與認證詳細分析之二(CERT.RSA剖析),如:
我們先看最後一步的已加密的Hash值,這是對CERT.SF檔案求Hash值然後使用私密金鑰加密後的結果。
再往上看密鑰,這裡的密鑰指的是非對稱式加密的公開金鑰。這個檔案中不儲存對稱式加密的私密金鑰。
CERT.RSA還儲存了發行者名稱和主體名稱,生效日期和終止日期等待。
瞭解了這個三個檔案的內容,我們也就知道了jarsigner都做了什麼事情。
2、簽名的作用
(1)保證內容的完整性
在安裝APK時,計算APK中每個資源的Hash值與MANIFEST.MF裡面的Hash值做對比;如果成功,再計算MANIFEST.MF檔案的Hash值與CERT.SF的Hash值做對比;如果成功,使用公開金鑰解密CERT.RSA已加密的Hash值,然後與對CERT.SF檔案求出的Hash值做對比;如果成功,表示驗證通過。
如果惡意修改代碼,再惡意修改MANIFEST.MF對應的Hash值,再惡意修改CERT.SF的Hash值,但是最後無法修改CERT.RSA裡面的Hash值,因為沒有私密金鑰。
1)如果當前的APK被篡改,直接放入手機中運行,第一步在計算APK中每個資源的Hash值與MANIFEST.MF裡面的Hash值做對比,這一步就Failed了。
2)如果當前的APK被篡改後重新簽名,由於系統中原有同樣包名的apk,發現與原有簽名的公開金鑰不一致,直接被reject。除非把原應用刪除,再安裝新的應用。
(2)shareUid
如果兩個應用shareUid,說明兩個應用可以對對方的私人目錄進行訪問,這就造成了安全隱患。如果360和QQ,sharedUid,那麼360就可以訪問QQ目錄下(/data/data/com.tencent/...)的私人資料。所以我們規定shardUid的兩個應用必須使用同樣的私密金鑰進行簽名,在CERT.RSA體現在公開金鑰一致。