iOS App 簽名原理

筆者接觸打包已經一段時間了,但一直對簽名都是似懂非懂,最近從加密數論知識起回看這部分知識,感受仍是有不少不懂的地方。html

先簡單說明一哈數學原理,而後說RSA 算法密鑰生成的步驟,最後回到 iOS 簽名打包,以及分享一哈利用重簽名作過的壞事(以學習、省時間爲目的)。git

非對稱加密

對稱加密是經過同一份密鑰加密和解密數據;而非對稱加密則有兩份密鑰,分別是公鑰和私鑰,用公鑰加密的數據,要用私鑰才能解密,用私鑰加密的數據,要用公鑰才能解密。github

(1)乙方生成兩把密鑰(公鑰和私鑰)。公鑰是公開的,任何人均可以得到,私鑰則是保密的。 (2)甲方獲取乙方的公鑰,而後用它對信息加密。 (3)乙方獲得加密後的信息,用私鑰解密。算法


數學原理

數學原理太長(難)不看篇:有一條等式,三個數字能夠關聯起來,從而達到互相驗證對方的數字是否配對。若是已知數字驗證等式很容易,可是若是未知這些數字,要推測出來對方的數字目前的技術還十分艱難。安全

互質的簡單結論

關於互質關係,咱們不可貴出如下結論:微信

  1. 任意兩個質數互質。網絡

  2. 一個數是質數,另外一個數只要不是它的倍數,兩數互質。app

  3. 一個質數與比它小的數,兩數互質。函數

  4. 1 和任意天然數互質。post

  5. p 是大於1的整數,p 和 p - 1互質。

  6. p 是大於1的奇數,p 和 p - 2互質。

歐拉函數

思考下面這個問題。

任意給定正整數n,請問在小於等於n的正整數之中,有多少個與n構成互質關係?

計算這個值的方法就叫作歐拉函數 ,以φ(n) 表示。

  • 若是n = 1,則φ(1) = 1 。

  • 若是n是質數,則 φ(n)=n-1 。由以上結論(3)得出。

  • 若是 n = p^k (p爲質數,k爲大於等於1的整數),那麼

image.png

由於 n 的因數只有 一、p、n,因此只要一個數因數分解不包含質數 p,纔可能與 n 互質。

而比p小,包含質數 p 的數有 1 *p、2 * p、3 * p、...、p^(k-1)×p,共有 p^(k-1) 個。減去便可。

好比 φ(8) = φ(2^3) =2^3 - 2^2 = 8 -4 = 4。

  • 若是 n 能夠分解成兩個互質 的整數之積。

  • n = p1 * p2

網上有種證實是「中國剩餘定理」,看不懂🙈。。。說說本身的理解。

好比 35 = 5 * 7。因爲35 的因數只有一、五、七、35。對於比35小的數來講,有7個5的倍數,5個7的倍數,則有12個,因爲35是重複計算的,則有11個。因此結果是 35 - 24 = 11。

**φ(n) = p1 * p2 - p1 - p2 + 1 = (p1 - 1)(p2 -1) = φ(p1)φ(p2) **

  • 由於任意大於1的正整數,均可以由一系列質數相乘所得。

image.png

根據第四條,注意是要互質的數 ,可得

image.png

再根據第三條,可得

image.png

image.png

這就是歐拉函數 。

歐拉定理

歐拉定理是RSA算法的核心。理解了這個定理,就可能能夠理解RSA。

直接給結論。感興趣的能夠本身去看證實(我也想看懂,但懵懵懂懂)。

image.png

即 a的φ(n)次方被n除的餘數爲1。

這個定理結合取餘分配率能夠用來簡化冪的模運算。

(ab)%c=(a%cb%c)%c

image.png

費馬小定理。

假設正整數 a 與質數 p 互質,n = p的狀況下,由結論(3)可得:

image.png

image.png

模反元素

若是 a 和 n 互質,那麼必定能夠找到整數 b,使得 ab - 1 被 n 整除。這時,b 就叫作 a 的「模反元素」。不難發現,若是b是模反元素,那麼b + a、b - a也是模反元素,模反元素不止一個 。

image.png

歐拉定理能夠用來證實模反元素必然存在。

image.png

密鑰生成的步驟

假設龍神要與那個ta 進行加密通訊,他要怎麼作才能瞞過八卦的羣衆呢?

第一步,隨機選擇兩個不相等的質數 。

龍神的幸運數字是61 那個ta 的幸運數字是53。

第二步,相乘。

n = 61 * 53 = 3233

寫成二進制是 110010100001,一共有12位,因此這個密鑰是12位。(一般1024位,更安全的場合2048位)。

**第三步,計算n的歐拉函數φ(n)。 **

φ(n) = (p-1)(q-1),φ(3233) = 3120。

**第四步,隨機選擇一個整數e,條件是1< e < φ(n),且e與φ(n) 互質。 **

龍神選了17。

第五步,計算e對於φ(n) 的模反元素d。

ed ≡ 1 (mod φ(n))

等價於

ed - 1 = kφ(n)

ex + φ(n)y = 1

17x + 3120y = 1

龍神算出一組整數解爲(2753,-15),即 d = 2753。

第六步,將 n 和 e 封裝成公鑰,n 和 d 封裝成私鑰。

因此公鑰(3233,17),私鑰(3233,2753)。

第七步, RSA 的可靠性。

回顧上面的步驟,一共出現了六個數字。

p = 61 q = 53 n = p * q = 3233 φ(n) = (p-1)(q-1) = 3120 e = 17 d = 2753

咱們上面提過,公鑰是公開的,因此 n 和 e 都是全部人能知道的。關鍵是d,若是泄漏了,就等於私鑰泄漏。

那麼,在已知 n 和 e 的狀況下,怎麼推導出 d?

(1) ed≡1 (mod φ(n))。只有知道e和φ(n),才能算出d。

(2) φ(n)=(p-1)(q-1)。只有知道p和q,才能算出φ(n)。

(3) n=pq。只有將n因數分解,才能算出p和q。

因此,只要因數分解n,就能夠獲得d。

可是,對於一個很大的質數,要因數分解是很是困難的事 。

因此,以目前的技術來看, RSA 是可靠的 。

加密和解密

公鑰:e 和 n 私鑰:d 和 n 明文:m 密文:c

公鑰和私鑰經過一條等式能互相驗證。有興趣的能夠本身研究。

RSA算法原理(二)

image.png

加密

假設龍神想說的悄悄話m,他就要用公鑰(3233,17)進行一次加密。這裏必須注意,m是小於n的整數。

而後算出下面式的c:

m^e ≡ c (mod n)

假設龍神說的悄悄話是 65,算出c 爲2790。

咱們要用到歐拉定理

65^17 mod 3233 = 2790

因此龍神就把2790發給那個ta。

解密

那個ta 收到2790後,就用私鑰(3233,2753)進行解密。

c^d ≡ m (mod n)

2790 ^ 2753 ≡ 65 (mod 3233)

因此原文就是65。

RSA 的優缺點

優勢: 目前來講安全。

缺點:

  • 速度慢

  • 只適合加密小數據


簡單介紹完一番我沒徹底理解的數學理論後,下面進入簽名環節。

數字簽名

做用

數字簽名的做用是利用非對稱加密方法,本身持有私鑰,公佈公鑰。互相加密以及驗證消息來源。

步驟

  1. 首先用一種算法,算出原始數據的摘要。需知足

    a. 若原始數據有任何變化,計算出來的摘要值都會變化。

    b. 摘要要夠短。這裏最經常使用的算法是MD5 。

  2. 生成一份非對稱加密的公鑰和私鑰,私鑰保留,公鑰公佈出去。

  3. 對一份數據,算出摘要 後,用私鑰加密 這個摘要,獲得一份加密後的數據,稱爲原始數據的簽名。把它跟原始數據一塊兒發送給用戶。

  4. 用戶收到數據和簽名後,用公鑰解密獲得摘要。同時用一樣的算法計算原始數據的摘要,對比這裏計算出來的摘要和用公鑰解密簽名獲得的摘要是否相等,若相等則表示這份數據中途沒有被篡改過,由於若是篡改過,摘要會變化 。

image.png

最簡單的簽名

image.png

iOS 設備用公鑰驗證一遍就知道該 App 是否是通過蘋果後臺認證的。若是被篡改過,確定是不行的。

然而,App 除了從 AppStore 下載,還有三種方式安裝:

  1. 開發 App 時能夠直接把開發中的應用安裝進手機進行調試。

  2. In-House 企業內部分發,能夠直接安裝企業證書籤名後的 APP。

  3. AD-Hoc 至關於企業分發的限制版,限制安裝設備數量,較少用。

因此蘋果的簽名還有額外的事情要作。

蘋果的 App 簽名

咱們來考慮上面第一種狀況。

首先,它既要有能不經蘋果私鑰驗證,立刻安裝的便利,又要通過蘋果驗證。

聽起來有點繞。蘋果採用的方案是雙層簽名。

image.png

  1. 在 Mac 生成一對公私鑰,這裏稱爲公鑰L私鑰L

  2. 蘋果本身有固定的一對公私鑰,私鑰在蘋果後臺,公鑰在每一個 iOS 設備上。

  3. 把公鑰 L 傳到蘋果後臺,用蘋果後臺裏的私鑰 A 去簽名公鑰 L。獲得一份數據包含了公鑰 L 以及其簽名,把這份數據稱爲證書 。

  4. 在開發時,編譯完一個 APP 後,用本地的私鑰 L 對這個 APP 進行簽名,同時把第三步獲得的證書一塊兒打包進 APP 裏,安裝到手機上。

  5. 在安裝時,iOS 系統取得證書,經過系統內置的公鑰 A,去驗證證書的數字簽名是否正確。

  6. 驗證證書後確保了公鑰 L 是蘋果認證過的,再用公鑰 L 去驗證 APP 的簽名,這裏就間接驗證了這個 APP 安裝行爲是否通過蘋果官方容許。(這裏只驗證安裝行爲,不驗證APP 是否被改動,由於開發階段 APP 內容老是不斷變化的,蘋果不須要管。)


除了要保證通過驗證外,蘋果還要防止濫用這種途徑下載。

想象一下,把真機連到 Mac 上,不就能想裝多少裝多少 App 嗎?那多部設備連到 Mac 上,App 不就能想裝在哪裝在哪嗎?

蘋果的方案是識別 設備和 App

想調試的設備必需要到開發者網站申請,而且設備數量是有限制的。

而後還針對每一個Bundle Identifier(App ID)配不一樣的證書。

這兩種數據都在上面第三步一塊兒組成證書(暫且這麼認爲)。

至此,證書就能實現 通過蘋果認證,而且能限制安裝設備數量和 App ID 。

固然,證書不止有這些信息,還有推送等權限,蘋果把這些權限開關統一稱爲Entitlements 。若是App 一開始的證書沒申請推送權限,那麼後面新增權限後,須要更新配置。

實際上,一個「證書」有規定的格式規範,不該把這些額外的信息往裏塞。因此上面的暫且這麼認爲部分是不對的。

因此蘋果把證書和額外信息包裝起來 ,把它叫作 Provisioning Profile 。

因此能拓展整個流程圖以下。

image.png

  1. 在你的 Mac 開發機器生成一對公私鑰,這裏稱爲公鑰L,私鑰L。L:Local
  2. 蘋果本身有固定的一對公私鑰,跟上面 AppStore 例子同樣,私鑰在蘋果後臺,公鑰在每一個 iOS 設備上。這裏稱爲公鑰A,私鑰A。A:Apple
  3. 把公鑰 L 傳到蘋果後臺,用蘋果後臺裏的私鑰 A 去簽名公鑰 L。獲得一份數據包含了公鑰 L 以及其簽名,把這份數據稱爲證書。
  4. 在蘋果後臺申請 AppID,配置好設備 ID 列表和 APP 可以使用的權限,再加上第③步的證書,組成的數據用私鑰 A 簽名,把數據和簽名一塊兒組成一個 Provisioning Profile 文件,下載到本地 Mac 開發機。
  5. 在開發時,編譯完一個 APP 後,用本地的私鑰 L 對這個 APP 進行簽名,同時把第④步獲得的 Provisioning Profile 文件打包進 APP 裏,文件名爲 embedded.mobileprovision,把 APP 安裝到手機上。
  6. 在安裝時,iOS 系統取得證書,經過系統內置的公鑰 A,去驗證 embedded.mobileprovision 的數字簽名是否正確,裏面的證書籤名也會再驗一遍。
  7. 確保了 embedded.mobileprovision 裏的數據都是蘋果受權之後,就能夠取出裏面的數據,作各類驗證,包括用公鑰 L 驗證APP簽名,驗證設備 ID 是否在 ID 列表上,AppID 是否對應得上,權限開關是否跟 APP 裏的 Entitlements 對應等。

關於證書等概念

上面的步驟對應到咱們日常具體的操做和概念是這樣的:

  1. 第 1 步對應的是 keychain 裏的 「從證書頒發機構請求證書」,這裏就本地生成了一對公私鑰,保存的 CertificateSigningRequest 就是公鑰,私鑰保存在本地電腦裏。
  2. 第 2 步蘋果處理,不用管。
  3. 第 3 步對應把 CertificateSigningRequest 傳到蘋果後臺生成證書,並下載到本地。這時本地有兩個證書,一個是第 1 步生成的,一個是這裏下載回來的,keychain 會把這兩個證書關聯起來,由於他們公私鑰是對應的,在XCode選擇下載回來的證書時,實際上會找到 keychain 裏對應的私鑰去簽名。這裏私鑰只有生成它的這臺 Mac 有,若是別的 Mac 也要編譯簽名這個 App 怎麼辦?答案是把私鑰導出給其餘 Mac 用,在 keychain 裏導出私鑰,就會存成 .p12 文件,其餘 Mac 打開後就導入了這個私鑰。
  4. 第 4 步都是在蘋果網站上操做,配置 AppID / 權限 / 設備等,最後下載 Provisioning Profile 文件。
  5. 第 5 步 XCode 會經過第 3 步下載回來的證書(存着公鑰),在本地找到對應的私鑰(第一步生成的),用本地私鑰去簽名 App,並把 Provisioning Profile 文件命名爲 embedded.mobileprovision 一塊兒打包進去。這裏對 App 的簽名數據保存分兩部分,Mach-O 可執行文件會把簽名直接寫入這個文件裏,其餘資源文件則會保存在 _CodeSignature 目錄下。 第 6 – 7 步的打包和驗證都是 Xcode 和 iOS 系統自動作的事。
  • CSR:Certificate Singing Request,證書籤名請求文件。

包含電腦的公鑰信息。因此建立時不須要填任何和發佈等有關的信息。

  • Certificates證書:發佈者證書。Apple Develop的ID 對某部電腦的受權證書。

內容是公鑰或私鑰,由其餘機構對其簽名組成的數據包。

電腦擁有這個證書後,有權對該Apple Developer的ID下全部App進行真機測試、打包、發佈。注意這裏,並未指定App,換句話說,和App無關。

  • CSR 和 Certificates 的聯繫

上面提到了Certificates包含了電腦的信息,這個信息來自於CSR。因此在建立Certificates時,須要提交CSR。至關於 Mac 的公鑰被蘋果私鑰 加密的過程。

  • p12: 本地私鑰,能夠導入到其餘電腦。

上面提到,擁有證書纔有權作那些事。若是另外一部電腦想發佈,也須要證書。若是又建立一個新證書也能解決,但通常一個開發者賬號建立一個發佈證書就夠了,並且蘋果對這證書數量有限制。這時候導出p12文件,至關於拷貝了一份私鑰。給另外一部電腦安裝後,另外一部電腦就有權了。

  • Entitlements:包含了 App 權限開關等信息。

  • Provisioning Profile: 描述文件。包含了證書、App ID、設備、Entitlements 等數據,並由後臺私鑰簽名的數據包。也稱爲PP文件,.mobileprovision後綴文件。

小結

CSR文件包含本地公鑰,被蘋果私鑰加密後生成 Cer 證書。該證書與權限、App ID、設備等數據經蘋果私鑰加密後生成 PP文件。裝到真機時,會對 PP文件總體進行驗證,還會對 PP 文件中的 Cer 證書進行驗證。


蘋果的 App 驗證

上面說了開發包的驗證流程

實際上 App 安裝以及每次啓動都會驗證。

各類證書的有效期

企業賬號發佈證書有效期是3年,而開發證書有效期爲1年,而描述文件開發發佈都是隻有1年有效期。

我的賬號開發證書發佈證書有效期都是1年,描述文件也全是1年有效期。


下面再說說企業包 和 AD - Hoc以及 App Store的驗證流程。

企業包和 AD - Hoc包驗證流程

企業包和 AD -Hoc 的區別在於企業包不會限制安裝設備數量,而且須要信任證書。

由於這兩種包不通過 App Store,對App的簽名是用證書籤名的。因此證書經蘋果發佈後,蘋果還想要限制的話,就必須檢查證書是否過時。這個步驟被放到了啓動 App 時。

所以,若是證書過時或者 revoke掉,開發者帳號被封禁,都會致使 App 啓動時閃退

  1. 證書過時或 revoke
  • app 會立刻不能使用,而且因爲 PP 文件包含它,也會失效。
  1. PP 文件過時 或 revoke
  • 也會閃退,但可能不會立刻反應過來,可能因爲網絡緣由等,不能立刻驗證失效。
  1. 帳號被註銷
  • 閃退

App Store 的驗證流程

blog.cnbang.net/wp-content/…

其實就是最簡單的驗證流程。

咱們上傳 App 到 App Store時驗證咱們的證書、PP文件。今後,與咱們的文件再無關係。

上傳後,蘋果在後臺直接用私鑰簽名 App 就能夠了。若是去下載一個 AppStore 的安裝包,會發現它裏面是沒有 embedded.mobileprovision 文件的,也就是它安裝和啓動的流程是不依賴這個文件,驗證流程也就跟上述幾種類型不同了。

已經在蘋果商店下載安裝的app不受影響(不管是過時仍是Revoke,甚至是開發者帳號被註銷,由於這個時候,對於app的簽名,是經過蘋果私鑰直接簽名的,沒有使用開發者名下的私鑰簽名)。

但App Store 會下架相關的 App。


筆者以前遇到一個場景就是,違規操做被註銷是沒辦法的(注意保護開發者帳號,能夠開啓雙重驗證,不要被偷去作馬甲包而後被舉報了)。那麼對於企業包證書過時問題怎麼處理呢?

由於有效期爲1年,咱們能夠申請兩個 PP 文件,相隔半年,差很少到時間發新版時就換個新 PP 文件。

更多能夠看iOS 各類證書的做用、有效期、過時的後果和解決辦法

重簽名

正常的打包流程就再也不說了。iOS完整的證書申請和打包過程

對 ipa 包進行修改後,因爲摘要變了,因此驗證會不經過。咱們能夠採用重簽名達到驗證的效果。經常使用於逆向別人的 App,微信多開等途徑。

App 的大體結構

打包出來 ipa 後,咱們解壓能夠看到大體結構。

image.png

  • 資源文件:例如圖片、html等等

  • CodeSignature/CodeResources:這是一個 plist 文件,可用文本查看,其中的內容就是程序包(不包括Frameworks)全部文件的簽名。意味着你的程序一旦簽名,就不能更改其中任何文件。

  • 可執行文件:此文件跟資源文件同樣須要簽名。

  • mobileprovision:校驗證書文件、Bundle ID。

  • Frameworks:程序引用的系統自帶的Frameworks,每一個Frameworks其實就是一個 app,也包含簽名信息。

iOS 系統驗證簽名有效性的過程

  1. 解壓ipa

  2. 取出 embedded.mobileprovision,校驗是否被篡改過

  3. 校驗全部文件的簽名

  4. 驗證設備是否符合embedded.mobileprovision 的信息

  5. 對比 Info.plist 的 Bundle Id 是否符合 embedded.mobileprovision  文件中的信息

重簽名的原理

既然簽名是由證書mobileprovision共同實現,那麼重簽名的過程其實就是將新的證書mobileprovision替換舊文件的過程,但因爲系統在驗證app是否合法的時候還會隨機驗證受權設備列表和Bundle ID、因此必須修改Bundle ID新的mobileprovision中的信息保持一致,不然將會有驗證失敗的風險。

重簽名的嘗試

筆者以前打的是企業包,針對不一樣客戶要實現不一樣 App Icon 和 App name等。若是一個一個打,一個打7分鐘。💩

利用重簽名,能夠快速替換 ipa 中的內容,實現裝逼的效果。

步驟以下

  1. 打包出一份 ipa。

  2. 修改 ipa 內對應文件。此時摘要變化了,至關於簽名失效,蘋果校驗時就知道該 app 被篡改 了。

  3. 重簽名

  • 3.1 刪除插件
  • 3.2 對FrameWorks進行簽名
  • 3.3 給可執行文件執行權限
  • 3.4 拷貝描述文件
  • 3.5 修改info.plist中的Bundle ID
  • 3.6 生成plist權限文件
  • 3.7 簽名整個APP
  • 3.8 生成ipa包

具體實現,更多可查看以前寫過的一篇文章 iOS —— 兩套自動打包腳本

參考

相關文章
相關標籤/搜索