前幾天實習上要打包出一個apk,而後上頭就發了我一個.keystore
文件,叫我打包的時候用這個簽名。當時我在想啊,原來我只是在學習計算機網絡的時候瞭解公鑰、密鑰的區別,在複習https後又加深瞭解了一下,但總之這些都不是我直接接觸的,都是些理論知識瞭解而過,如今遇到了,我就在想Android的這個打包時爲啥要簽名?簽名不是應該存在於網絡傳輸中的嗎?java
原來才學習Android的時候作了個音樂的app,使用的是喜馬拉雅的SDK,其中引入後就叫你必須使用混淆,當時第一次接觸了混淆。後來反編譯過一些軟件,發現有些包名爲a,b...這樣的,才瞭解了下混淆的做用。android
這兩個知識點呢都是保證了咱們應用的安全,並且都是在打包的時候使用到的,我就把他們總結在了一塊兒去學習。c++
最後真的感謝我選擇了Android,咱們大學快結束了才學習了編譯原理、c++,當時我認爲這兩門課對咱們軟件的學生可能用處不大,由於大部分同窗走的方向都是java方向,當我開始作Android直播方向的畢設的時候,我感受學校開的全部課程都能聯繫起來了
git
圖爲典型的Android應用模塊的編譯流程 Android編譯流程的步驟:github
ps:算法
- 若是您使用的是 apksigner,則只能在爲 APK 文件簽名以前執行 zipalign。若是您在使用 apksigner 爲 APK 簽名以後對 APK 進行進一步更改,則簽名將會失效。
- 若是您使用的是 jarsigner,則只能在爲 APK 文件簽名以後執行 zipalign。
ps2:緩存
- 咱們常常直接解壓一些apk的時候會發現有不少的classes.dex文件,默認的dex文件應該是一個的,可是每一個dex文件的方法數不能超過65535。咱們只要在glide下配置multiDexEnabled true就行了
![]()
平時呢咱們對這種初級開發者,一個應用誕生後,真的就是一個屬於本身的app了,通常就調試運行在本身的手機上,有些時候甚至還作不到多機型適配,出於炫耀等緣由,你可能會將你的app打包成apk,而後呢丟在一個服務器上,生成一個二維碼,發個朋友圈(別問我爲啥這麼清楚,問就是我有個朋友)。這種時候咱們徹底沒接觸到簽名啊。安全
當時的我認爲只要不發佈到各類應用商店就能夠不用簽名的,我上官方文檔查了下,發現了下面這段話:服務器
Android 系統要求全部 APK 必須先使用證書進行數字簽名,而後才能安裝到設備上或進行更新。網絡
咱們通常調試build出的apk都是app-debug.apk
,按照上文的說法呢!系統應該是自動幫咱們進行了簽名,但簽名的文件呢?沒想到那麼好找,我一點開.android
文件夾就看到了debug.keystore
,沒錯這就是本機默認的數字簽名。
您首次在 Android Studio 中運行或調試項目時,IDE 會自動在 $HOME/.android/debug.keystore 中建立調試密鑰庫和證書,並設置密鑰庫和密鑰密碼。
官文中也能找到對應的解釋(並且還告訴了咱們在首次運行和調試的時候自動建立的,這就意味着你安裝IDE的時候是不存在的,也就是說每臺機器產生的調試密鑰庫和證書應該是不一樣的)
咱們查看下這裏面的內容:
嗯好,看完就到了解決最初問題的時候了。
官文中的簽名注意事項明確的告訴了咱們簽名的做用。
主要有如下三點:
- 應用升級:當安裝應用的更新時,系統會比較新版本和現有版本中的證書。若是證書匹配,則系統容許更新。若是使用不一樣的證書爲新版本簽名,您必須爲應用分配另外一個軟件包名稱 - 在此狀況下,用戶會將新版本做爲全新應用進行安裝。
- 應用模塊化:Android 容許經過同一證書籤名的多個 APK 在同一個進程中運行(若是應用請求這樣作),以便系統將其視爲單個應用。這樣一來,您即可以按模塊部署您的應用,而且用戶能夠獨立更新每一個模塊。
- 經過權限共享代碼/數據:Android 提供了基於簽名的權限執行機制,以便一個應用能夠將功能提供給使用指定證書籤名的另外一個應用。經過使用同一個證書爲多個 APK 簽名並使用基於簽名的權限檢查功能,您的應用能夠採用安全的方式共享代碼和數據。
在實際的應用中呢,我遇到了這種狀況,當前的設備上已經安裝該應用的apk,但公司叫我從新開發了,我開發完成後直接使用app-debug.apk
在設備上進行安裝,就出現了該錯誤。(解決方法一,卸載了原程序,再安裝,但這就將緩存的數據給清空了。這讓我想到了「明日方舟」,每次大的版本更新都要將原程序卸載了,安裝新的apk,安裝後得從新登陸)(解決方法二,將簽名一塊兒發給程序猿——咱們,打包的時候使用相同的簽名)
這就體現出了簽名最經常使用的做用之一「應用升級」。這也是我想了解簽名與寫下這篇博客的導火索之一。
回答這個問題呢,就須要去了解幾個名詞:
證書 公鑰證書(.der 或 .pem 文件,也稱爲數字證書或身份證書)包含公鑰/私鑰對中的公鑰,以及能夠標識持有對應私鑰的全部者的一些其餘元數據(例如名稱和位置)。
在爲您的應用簽名時,簽名工具會將該證書附加到應用。該證書會將 APK 或 app bundle 與您和您對應的私鑰相關聯。這有助於 Android 確保您應用往後的全部更新都真實可靠,而且來自原始做者。用於建立此證書的密鑰稱爲應用簽名密鑰。
您能夠從 Play 管理中心的「應用簽名」頁面下載您的應用簽名密鑰和上傳密鑰的證書,以便向 API 提供商註冊您的密鑰。您能夠與任何人共享該證書。它不包含您的私鑰。
每一個應用在其整個生命週期內必須使用同一證書,以便用戶可以以應用更新的形式安裝新版本。要詳細瞭解讓全部應用在其整個生命週期內使用同一證書的好處,請參閱上面的簽名注意事項。
證書指紋是證書獨一無二的簡短表示形式,一般 API 提供商會要求同時提供證書指紋和軟件包名稱,以註冊使用其服務的應用。您能夠在 Play 管理中心的「應用簽名」頁面上找到上傳證書和應用簽名證書的 MD五、SHA-1 和 SHA-256 指紋。您還能夠從同一頁面下載原始證書 (.der) 來計算其餘指紋。
如下是您應該瞭解的不一樣類型的密鑰和密鑰庫:
應用簽名密鑰:用於爲用戶設備上安裝的 APK 簽名的密鑰。做爲 Android 安全更新模型的一部分,應用簽名密鑰在應用的整個生命週期內保持不變。應用簽名密鑰屬於私鑰,所以必須保密。不過,您能夠與他人共享使用應用簽名密鑰生成的證書。
上傳密鑰:在爲 Google Play 應用簽名計劃上傳 app bundle 或 APK 以前用於爲其簽名的密鑰。您必須爲上傳密鑰保密。不過,您能夠與他人共享使用上傳密鑰生成的證書。您能夠經過如下某種方式生成上傳密鑰:
Java 密鑰庫(.jks 或 .keystore):一個二進制文件,用做證書和私鑰的存儲區。
Play Encrypt Private Key (PEPK) 工具:使用此工具可從 Java 密鑰庫中導出私鑰,並對私鑰加密以便傳輸到 Google Play。在提供應用簽名密鑰以供 Google 使用時,請選擇從 Java 密鑰庫導出並上傳密鑰選項,並按說明下載和使用此工具。或者,您也能夠選擇導出並上傳密鑰(不使用 Java 密鑰庫)選項,如下載、查看和使用 PEPK 工具的開放源代碼。
(以上都是官文對應用簽名要掌握的知識點的概述——原文引用來自密鑰、證書和密鑰庫)
經過上文能夠總結出:Android簽名機制不能阻止APK包被修改,但修改後的再簽名沒法與原先的簽名保持一致(除非你擁有私鑰)。也就是說若是你的軟件仍是會被反編譯的,但其餘人反編譯後再打包的話實際上是另外一個應用。(好比咱們原來玩的諾基亞小遊戲的時候常常會有些是漢化版,而後咱們下下來是不會替換掉原來的程序,我就想起當時玩一個叫「上古2」的網遊,下了個雙開的版本,如今才知道原來那個被破解了而後從新打包的應用啊)
綜上所述:簽名機制實際上是對APK包完整性和發佈機構惟一性的一種校驗機制。能簡單的保證apk的安全,但頗有限,應該說是一個軟件最基本的防護。咱們能夠適當的提高下安全係數,在程序運行的時候進行簽名對比,但被破解後,讓程序跳過簽名對比的部分,就能破壞了這最基本的防護。
簽名的原理:咱們能夠看debug.keystore
中寫了簽名算法名稱:SHA1withRSA
。 能夠得出該apk是使用SHA1-RSA算法,用私鑰進行簽名的。
SHA-1:是一種密碼散列函數,雖然該密碼如今已經不夠安全了,但還在被普遍的使用。它把任意長度的輸入,經過散列算法變成固定長度的輸出。
RSA:是一種非對稱加密算法。用私鑰經過RSA算法對SHA-1的輸出信息進行加密。
在安裝時只能使用公鑰才能解密RSA加密後的信息。解密以後,將它與SHA-1的輸出信息進行對比,若是相符,則代表內容沒有被異常修改。
混淆處理:縮短類和成員的名稱,從而減少 DEX 文件的大小。
混淆處理的目的是經過縮短應用的類、方法和字段的名稱來減少應用的大小。
雖然混淆處理不會從應用中移除代碼,但若是應用的 DEX 文件將許多類、方法和字段編入索引,那麼混淆處理將能夠顯著縮減應用的大小。 不過,因爲混淆處理會對代碼的不一樣部分進行重命名,所以在執行某些任務(如檢查堆棧軌跡)時須要用到額外的工具。
此外,若是您的代碼依賴於應用的方法和類的可預測命名( 例如,使用反射時),您應該將相應簽名視爲入口點併爲其指定保留規則。
能夠獲得混淆的目的就是縮小應用的大小,但不少地方都說混淆能夠保護代碼的安全,由於他下降了代碼的可讀性,讓反編譯後的破解得花費一些時間。這雖然可能不是混淆出現的目的之一,但人們將他活學活用了,發現了它另外的價值。
混淆是不可逆的,在混淆的過程當中一些不影響正常運行的信息將永久丟失,這些信息的丟失使程序變得更加難以理解。
我曾經由於以爲某app的某功能實現效果特別好,而後將其反編譯後,發現混淆真的頗有用,可能應爲我看小說就幾個名字看了一半後都除了主角,其餘人都對不上號吧,常常還倒回去找下這我的是誰?(要是他是英文的名字,我更加記不住了,可能都不會回去找,這種狀況就須要一張紙寫下相應名字間的關係一塊兒夾在書裏了,這可能也算「混淆」吧)
最後呢!就是市面上應該沒有一款軟件是100%安全的,只是他們的加密手段複雜可能還會隨時間修改,破解它多是成本問題。
再最後呢!PC上的反編譯軟件你們都很熟悉(apktool + dex2jar + jd-gui)
手機上呢我挺喜歡一款叫「開發助手」的軟件的(好像是某滴滴大佬開發的),能看應用佈局、屏幕取色、app用的什麼加密軟件等等,功能性我的認爲比「MT管理器」要好吧。
Android studio 中咱們可使用 build -> Analyze APK... 去分析apk,而後去進一步優化咱們apk的大小。