針對 Android 中簽名的相關問題,做一些記錄整理。
以前,遇到許多關于簽名的問題
- APK 安裝時的校驗
- 成為 Android 系統級應用
- 查看應用的MD5或者是SHA1信息
- v2簽名
- ….
這些問題都將在后面得到答案。
什么是簽名
首先,什么是簽名?為什么需要簽名?
在生活中,一般我們對某個文件進行簽名,代表簽名者對此文件的認可,防止簽名者抵賴,同時防止文件被他人篡改。在計算機中也一樣,簽名就是對某個文件的一種認證過程,而簽名校驗就可以有效防止文件被惡意篡改,證明此文件是簽名者的原始文件。
簽名的流程如下:
利用一個單向哈希函數對原始文件進行運算,生成數字摘要,然后用私鑰加密這個數字摘要,這個加密后的數字摘要就是數字簽名,最后將數字簽名和原始文件一起打包成一個新的文件,如此,這個原始文件就被簽名了。
校驗簽名的流程如下:
拿到被簽名后的文件之后,首先提取出原始文件與簽名,然后使用相同的單向哈希函數對原始文件運算,生成數字摘要,然后用公鑰解密數字簽名,然后對比兩個數字摘要,如果相同就表示校驗成功。
數字簽名是非對稱加密與數字摘要的組合應用,它有兩種功效:
- 確定文件(消息)確實是由簽名者簽名并發出來的,因為別人假冒不了簽名者的簽名。
- 數字簽名能確定消息的完整性。
當然,數字簽名一般不單獨使用,基本都是用在數字證書里面。
Android 簽名
Android 要求所有已安裝的應用程序都使用數字證書做數字簽名,數字證書的私鑰由開發者持有。
Android 使用數字證書作為標識應用程序開發者的一種方式,并在應用程序之間建立信任的關系,證書并不用來控制用戶能否安裝那個應用程序。
Android 的數字證書與普通數字證書最大的區別是,Android 數字證書并不需要權威的數字證書簽名機構(CA)認證,它只是用來讓應用程序包自我認證的,完全可以使用自簽名證書(seft-signed certificates)。
沒有正確簽名的應用,Android系統不會安裝或運行,此規則適用于任何地方運行的Android系統,不管是在模擬器還是在真實設備上。即使是開發人員調試時的應用程序,也是使用了默認的簽名文件 (目錄:用戶名/.android/debug.keystore,密碼:android)進行簽名的。
只有簽名文件相同且包名相同的 apk 才可以覆蓋安裝并保留用戶信息,這樣做是為了防止已安裝的應用被惡意的第三方覆蓋或替換。
此外,數字證書都是有有效期的,Android 只是在應用程序安裝的時候才會檢查證書的有效期。如果程序已經安裝在系統中,即使證書過期也不會影響程序的正常功能。
Android 簽名的作用
Android 簽名的主要作用是為了
- 應用程序升級:如果你希望用戶無縫升級到新的版本,那么你必須用同一個證書進行簽名。這是由于只有以同一個證書簽名,系統才會允許安裝升級的應用程序。如果你采用了不同的證書,那么系統會要求你的應用程序采用不同的包名稱,在這種情況下相當于安裝了一個全新的應用程序。如果想升級應用程序,簽名證書要相同,包名稱要相同!
- 應用程序模塊化:Android系統可以允許同一個證書簽名的多個應用程序在一個進程里運行,系統實際把他們作為一個單個的應用程序,此時就可以把我們的應用程序以模塊的方式進行部署,而用戶可以獨立的升級其中的一個模塊
- 代碼或者數據共享:Android提供了基于簽名的權限機制,那么一個應用程序就可以為另一個以相同證書簽名的應用程序公開自己的功能。以同一個證書對多個應用程序進行簽名,利用基于簽名的權限檢查,你就可以在應用程序間以安全的方式共享代碼和數據了。
所以一旦給Apk簽名并上線后,簽名文件和密碼別名等一定要記住不能丟失,否則會損失用戶且帶來災難性的后果.
簽名文件格式
簽名文件格式有很多種,這里主要是介紹 Android 相關的,比如最早的 keystore、jks、pem/pk8等。
- KeyStore: KeyStore 是 Eclipse 開發 Android 的時候最早的簽名文件了。
- JKS (Java key store): jks 是目前 Android Studio 中創建簽名文件的格式 (Build -> Generate Signed APK) 即可創建和使用簽名文件為對應apk進行簽名
- pem/pk8 :這個是系統的簽名文件,Android系統在編譯的時候也是需要簽名,所以這個是系統的簽名文件,如果想使自己的應用變成系統應用,則必須使用系統的簽名文件進行簽名。
Signature Versions V1、V2
在新的 Android studio 版本中,出現了 v2 簽名,先看看官方解釋:
V1:通過ZIP條目進行驗證,這樣APK 簽署后可進行許多修改,可以移動甚至重新壓縮文件。
V2:驗證壓縮文件的所有字節,而不是單個 ZIP 條目,因此,在簽名后無法再更改(包括 zipalign)。正因如此,現在在編譯過程中,我們將壓縮、調整和簽署合并成一步完成。好處顯而易見,更安全而且新的簽名可縮短在設備上進行驗證的時間(不需要費時地解壓縮然后驗證)。
只勾選v1簽名并不會影響什么,但是在7.0上不會使用更安全的驗證方式 。
只勾選V2簽名7.0以下會直接安裝完顯示未安裝,7.0以上則使用了V2的方式驗證
同時勾選V1和V2則所有機型都沒問題
或者在app的build.gradle的android標簽下加入如下
signingConfigs {
debug {
v1SigningEnabled true
v2SigningEnabled true
}
release {
v1SigningEnabled true
v2SigningEnabled true
}
}
建議把V1和V2兩個選項全部勾選,如果全部勾選出現了問題,那么可以忽略這種新的簽名機制,只勾選第一個選項(V1),依舊使用我們之前老的簽名機制。
生成數字證書
生成數字證書有兩種方式,包括帶圖形界面的 AS,以及命令行的keytool。
Android Studio
在 Android studio 中生成簽名文件非常簡單,build -> Generate Signed APK -> Create new…
填寫完信息之后就生成了數字證書,之后下一步就給 apk 簽名上了。
AS 簽名帶界面的,自然方便,但有時候需要使用命令行工具。
簽名相關的兩個工具都在 JDK 中
- keytool 是個密鑰和證書管理工具,可以用來生成證書。
- jarsigner 工具利用密鑰倉庫中的信息來產生或校驗 Java 存檔 (JAR) 文件的數字簽名
Keytool 生成
使用keytool生成證書:
keytool -genkey -keystore test.keystore -alias test -keyalg RSA -validity 10000
參數解釋:
- -genkey 產生證書文件
- -keystore 指定密鑰庫的.keystore文件中
- -alias 指定別名
- -keyalg 指定密鑰的算法,這里指定為RSA(非對稱密鑰算法)
- -validity 為證書有效天數
jarsigner 簽名
數字證書生成后,需要使用 jarsigner 來簽名
jarsigner -verbose -keystore test.keystore -signedjar -signed.apk unsigned.apk 'test'
參數說明:
- -verbose:指定生成詳細輸出
- -keystore:指定數字證書存儲路徑
- -signedjar:該選項的三個參數為 -簽名后的apk包,-未簽名的apk包,-數字證書別名(注意順序)
查看簽名文件
在使用一些第三方庫時(如分享、百度地圖),有時會被要求提供 MD5 或者 SHA1值。
查看簽名文件信息需要用到 keytool 工具,keytool 是 JDK 自帶的工具,需要配置環境變量,輸入以下命令:
keytool -list -v -keystore <keystore文件名>
例如,查看位于 .android
目錄下默認的簽名文件 debug.keystore
的信息:
此命令需要提供 簽名文件的密碼, debug.keystore
文件的別名是 androiddebugkey
,密碼是 android
,之后輸出了簽名文件的 MD5、SHA1、SHA256的值。
系統簽名
普通應用程序的權限受限制,需要系統應用權限才行,因此在定制化系統中,需要將應用程序升級為系統應用程序,這時候就需要系統簽名。
這里有兩種方案。
使用Android簽名工具重新簽名
提供對應平臺簽名文件「platform.pk8」和「platform.x509.pem」,如果是定制系統,為了省事兒,直接找編譯系統的兄弟討要,如果是google 原生系統,則可以到源碼處下載,8.0.0_r4 的兩個文件地址在此 ,其他平臺版本的位置類似。
提供簽名工具「signapk.jar」,8.0.0_r4的簽名工具地址在此,其他平臺版本的位置類似。
將簽名證書「platform.pk8」、「platform.x509.pem 」,簽名工具「signapk.jar 」放置在同一個文件夾,執行命令
java -jar signapk.jar platform.x509.pem platform.pk8 Demo.apk signedDemo.apk
生成系統debug.keystore文件
這種方式的好處就是不用每次都手動打包,可以直接配置在 AS 中,同樣需要前面的平臺簽名文件「platform.pk8」和「platform.x509.pem」。
- 把pkcs8 格式的私鑰轉化成 pkcs12 格式:
openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out shared.priv.pem -nocrypt
- 把 x509.pem 公鑰轉換成 pkcs12 格式
openssl pkcs12 -export -in platform.x509.pem -inkey shared.priv.pem -out shared.pk12 -name androiddebugkey
密碼都是:android
- 生成debug.keystore
keytool -importkeystore -deststorepass android -destkeypass android -destkeystore debug.keystore -srckeystore shared.pk12 -srcstoretype PKCS12 -srcstorepass android -alias androiddebugkey
原文地址:https://www.deemons.cn/2018/05/10/Android-%E7%AD%BE%E5%90%8D%E9%82%A3%E7%82%B9%E4%BA%8B%E5%84%BF/