你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS 開發 code sign 代碼簽名深入剖析

iOS 開發 code sign 代碼簽名深入剖析

編輯:IOS開發綜合

前言

這裡寫圖片描述
三個模塊:

//代碼簽名授權
Code Signing Entitlements
//代碼簽名身份
Code Signing Identity
//描述文件/配置文件
Provisioning Profile

1.點擊這裡—-蘋果官網code sign guide

2.代碼簽名 (code signing) 和配置文件 (provisioning),是做iOS開發繞不過的坎,報錯的時候也是很不容易解決的,終究其原因,就是對蘋果為iOS開發設置的一整套安全機制理解不到位導致的,平時大家都集中時間處理開發中遇到的需求問題,在這裡投入的時間不夠,到時出現錯誤時,不曉得從哪裡下手

3.蘋果的很多東西都是閉源的,代碼簽名就是一個難以理解的神秘黑盒,我們無法直接看到代碼簽名的運作過程,它們隱藏在 iOS 系統內部和 SDK 之中.想要理解code sign的運作,就不得不了解證書和秘鑰了

證書( Certificates)和密匙(Keys)

作為一個 iOS 開發者,在你開發使用的機器上應該已經有一個證書,一個公鑰,以及一個私鑰。這些是代碼簽名機制的核心

打開–鑰匙串—我的證書
這裡寫圖片描述

可以看到所有你持有的私鑰相對應的證書。 要用一個證書設置代碼簽名,必須擁有私鑰,所以所有擁有私鑰的證書都會被列在這裡。 如果擁有一個證書的私鑰,可以展開證書並將它的私鑰顯示出來: 如果要導出證書,例如為了備份(強烈建議進行),一定要記得展開證書那一條顯示出私鑰並將兩行都選中。且導出後的證書就是.p12格式的文件,做推送時,就是這樣的文件

證書/認證機構/有效期

一個證書是一個公鑰加上許多附加信息,這些附加信息都是被某個認證機構(Certificate Authority 簡稱 CA)進行簽名認證過的,認證這個證書中的信息是准確無誤的。 對於 iOS 開發來說這個認證機構就是蘋果的認證部門 Apple Worldwide Developer Relations CA。 認證的簽名有固定的有效期,這就意味著當前系統時間需要被正確設置,因為證書是基於當前時間進行核對。這也是為什麼將系統時間設定到過去會對 iOS 造成多方面破壞的原因之一。 對於iOS開發,有兩種證書:開發證書(Develope)和發布證書(Distribution).iOS 系統會利用這個信息來判斷你的應用是運行在開發模式下還是發布模式,並據此判斷以切換應用運行規則

證書/簽名/公鑰/私鑰

為了讓擁有公鑰的證書起作用,我們需要有私鑰。 私鑰是你在為組成應用的二進制文件進行簽名時派上用場的。沒有私鑰,你就無法用證書和公鑰對任何東西設置簽名. 簽名過程本身是由命令行工具 codesign 來完成的。 如果你在 Xcode 中編譯一個應用,這個應用構建完成之後會自動調用 codesign 命令進行簽名,codesign 也正是給你提供了許多格式友好並且有用錯誤信息的那一個工具。你可以在 Xcode 的 project settings 中設置代碼簽名信息。
這裡寫圖片描述

注意:

Xcode 只允許在有限的選項中進行選擇,這些選項都是既擁有公鑰也擁有私鑰的證書。 如果在選項中沒有出現你想要的那一個,那麼你需要檢查的第一件事情就是你是否擁有這個證書的私鑰。 在這裡需要區分開用於開發測試還是用於發布,如果想要在機器上測試你的應用,你需要用用於開發測試的那一對密匙來進行簽名,如果你是要發布應用,無論是給測試人員還是發布到 APP Store,你需要用用於發布的那一對密匙來進行簽名。 Xcode 6之後 的 project settings 中出現了設置配置文件(Provisioning Profile)的選項。如果你選擇了某一個配置文件,你必須選擇這個配置文件的證書中所包含的公鑰所對應的那個密匙對,或者你可以選擇讓 Xcode 自動完成正確的設置

已簽名應用–簽名信息的查看和修改

原理理解:一個已簽名的可執行文件的簽名包含在 Mach-O 二進制文件格式中;對於例如腳本這樣的非 Mach-O 可執行文件,就存放在該文件系統的的擴展屬性中。這種做法使得在 OS X 和 iOS 上的任何可執行二進制文件都可以被設置簽名:不論是動態庫,命令行工具,還是 .app 後綴的程序包。這也意味著設置簽名的過程實際上會改動可執行文件的文件內容,將簽名數據寫入二進制文件中。 如果你擁有一個證書和它的私鑰,那麼用 codesign 來設置簽名非常簡單,我們現在嘗試用下面列出的這個證書來為 Example.app 設置簽名:
$ codesign -s 'iPhone Developer: [email protected] (4KPK36MFV)' Example.app
如果你想為某一個 app 程序包重新設置簽名,那麼這個工具就很有用了。為了重新設置簽名,你必須帶上 -f 參數,有了這個參數,codesign 會用你選擇的簽名替換掉已經存在的那一個:
$ codesign -f -s 'iPhone Developer: [email protected] (4KPK36MFV)' Example.app

codesign 還可以為你提供有關一個可執行文件簽名狀態的信息,這些信息在出現不明錯誤時會提供巨大的幫助。舉例來說,$ codesign -vv -d Example.app 會列出一些有關 Example.app 的簽名信息

'Executable'=/Users/toto/Library/Developer/Xcode/DerivedData/Example-cfsbhbvmswdivqhekxfykvkpngkg/Build/Products/Debug-iphoneos/Example.app/Example
'Identifier'=ch.kollba.example
'Format'=bundle with Mach-O thin (arm64)
CodeDirectory v=20200 size=26663 flags=0x0(none) hashes=1324+5 location=embedded
Signature size=4336
'Authority'=iPhone Developer: [email protected] (4KPK36MFV)
'Authority'=Apple Worldwide Developer Relations Certification Authority
'Authority'=Apple Root CA
'Signed Time'=29.09.2014 22:29:07
'Info.plist entries'=33
'TeamIdentifier'=DZM8538E3E
Sealed Resources version=2 rules=4 files=120
Internal requirements count=1 size=184

以 Authority 開頭的那三行。這三行告訴你到底是哪一個證書為這個 app 設置了簽名。在這裡當然是我的證書,iPhone Developer: [email protected] (4KPK36MFV)。我的這個證書則是被證書 Apple Worldwide Developer Relations Certification Authority 設置了簽名的,依此類推這個證書則是被證書 Apple Root CA 設置了簽名。

在 Format 中也包含了一些關於代碼的信息:Example.app 並不單單是一個可執行文件,它是一個程序包,其中包含了一個 arm64 二進制文件。從 Executable 中的路徑信息你可以看出,這是一個以測試為目的的打包,所以是一個 Mach-O thin 的二進制文件。

在一堆診斷信息中還包含了兩個非常有趣的條目。 Identifier 是我在 Xcode 中設置的 bundle identifier。 TeamIdentifier 用於標識我的工作組(系統會用這個來判斷應用是否是由同一個開發者發布)。此外用於發布應用的證書中也包含這種標識,這種標識在區分同一名稱下的不同證書時非常有用。

下面我們來檢查一下封印是否完好:

$ codesign --verify Example.app

授權機制 (Entitlements) 和配置文件 (Provisioning)

原理理解:

即使你可以讓應用運行起來,在 iOS 上你的應用能做什麼依然是受限制的。這些限制是沙盒管理的。

沙盒和代碼簽名機制是不同的。代碼簽名保證了這個應用裡所包含的內容正如它所說的那樣不多不少,而沙盒則是限制了應用訪問系統的資源。

這兩種技術是相互合作來發揮作用的,它們都能阻止你的應用運行,也都能在 Xcode 中引起奇怪的問題。但是在日常開發過程中,沙盒可能會更經常引起問題。沙盒機制在什麼時候會引起問題呢,大多數情況下都是由於一個叫做授權的機制決定的。

授權機制

授權機制決定了哪些系統資源在什麼情況下允許被一個應用使用。簡單的說它就是一個沙盒的配置列表,上面列出了哪些行為被允許,哪些會被拒絕。

很可能你已經猜到授權機制也是按照 plist 文件格式來列出的。Xcode 會將這個文件作為 –entitlements 參數的內容傳給 codesign ,這個文件內部格式如下:





        application-identifier
        7TPNXN7G6K.ch.kollba.example
        aps-environment
        development
        com.apple.developer.team-identifier
        7TPNXN7G6K
        com.apple.developer.ubiquity-container-identifiers
        
                7TPNXN7G6K.ch.kollba.example
        
        com.apple.developer.ubiquity-kvstore-identifier
        7TPNXN7G6K.ch.kollba.example
        com.apple.security.application-groups
        
                group.ch.kollba.example
        
        get-task-allow
        

在 Xcode 的 Capabilities 選項卡下選擇一些選項之後,Xcode 就會生成這樣一段 XML。 Xcode 會自動生成一個 .entitlements 文件,然後在需要的時候往裡面添加條目。

當構建整個應用時,這個文件也會提交給 codesign 作為應用所需要擁有哪些授權的參考。這些授權信息必須都在開發者中心的 App ID 中啟用,並且包含在配置文件中。在構建應用時需要使用的授權文件可以在 Xcode build setting 中的 code signing entitlements 中設置。

$ codesign -d --entitlements - Example.app 

會列出一個和前面的很像的 XML 格式的屬性列表。你可以將這個文件的內容添加進一個腳本,每次構建應用時用腳本檢查是否包含了推送服務的授權信息,以此確保推送服務工作正常。在這裡推送服務只是一個例子,你使用的服務越多,這樣的時候都添加推送通知的授權,以保證可以注冊推送通知。Xcode 6 之後,授權信息列表會以 Example.app.xcent 這樣的名字的文件形式包含在應用包中。

配置文件

在整個代碼簽名和沙盒機制中有一個組成部分將簽名,授權和沙盒聯系了起來,那就是配置文件 (provisioning profiles)。

每一個 iOS 開發者可能都花費過相當的時間研究如何設置配置文件,這個環節也正是會經常出問題的地方。

一個配置文件中存放了系統用於判斷你的應用是否允許運行的信息,這就意味著如果你的配置文件有問題,修復起來會相當煩人。

一個配置文件是一組信息的集合,這組信息決定了某一個應用是否能夠在某一個特定的設備上運行。配置文件可以用於讓應用在你的開發設備上可以被運行和調試,也可以用於內部測試 (ad-hoc) 或者企業級應用的發布。Xcode 會將你在 project setting 中選擇的配置文件打包進應用。
這裡寫圖片描述

我們下面來仔細研究一下配置文件。如果你要在自己的機器上找到配置文件,在這個目錄下 ~/Library/MobileDevice/Provisioning Profiles。Xcode 將從開發者中心下載的全部配置文件都放在了這裡。

這裡寫圖片描述

配置文件並不是一個 plist 文件,它是一個根據密碼訊息語法 (Cryptographic Message Syntax) 加密的文件

采用 CMS 格式進行加密使得配置文件可以被設置簽名,所以在蘋果給你這個文件之後文件就不能被改變了。配置文件的簽名和應用的簽名不是一回事,它是由蘋果直接在開發者中心 (developer portal) 中設置好了的。

某些版本的 OpenSSL 可以讀取這種格式,但是 OS X 自帶那個版本並不行。幸運的是命令行工具 security 也可以解碼這個 CMS 格式,那麼我們就用 security 來看看一個 .mobileprovision 文件內部是什麼樣子:

$ security cms -D -i example.mobileprovision

這個命令會輸出簽名信息中的內容,接下來你會得到一個 XML 格式的 plist 文件內容輸出。

這個列表中的內容是 iOS 用於判斷你的應用是否能運行在某個設備上真正需要的配置信息,每一個配置文件都有它自己的 UUID 。Xcode 會用這個 UUID 來作為標識,記錄你在 build settings 中選擇了哪一個配置文件。

首先來看 DeveloperCertificates 這項,這一項是一個列表,包含了可以為使用這個配置文件的應用簽名的所有證書。如果你用了一個不在這個列表中的證書進行簽名,無論這個證書是否有效,這個應用都無法運行。所有的證書都是基於 Base64 編碼符合 PEM (Privacy Enhanced Mail, RFC 1848) 格式的。要查看一個證書的詳細內容,將編碼過的文件內容復制粘貼到一個文件中去,像下面這樣:

-----BEGIN CERTIFICATE-----
MIIFnjCCBIagAwIBAgIIE/IgVItTuH4wDQYJKoZIhvcNAQEFBQAwgZYxCzA…
-----END CERTIFICATE-----

可能會注意到在 Entitlements 一項中包含了你的應用的所有授權信息,這些授權信息是你在開發者中心下載配置文件時在 App ID 中設置的,理想的情況下,這個文件應該和 Xcode 為應用設置簽名時使用的那一個同步,但這種同步並不能得到保證。這個文件的不一致是比較難發現的問題之一。

舉例來說,如果你在 Xcode 中添加了 iCloud 鍵值對存儲授權 (com.apple.developer.ubiquity-kvstore-identifier),但是沒有更新,重新設置並下載新的配置文件,舊的配置文件規定你的應用並沒有這一項授權。那麼如果你的應用使用了這個功能,iOS 就會拒絕你的應用運行。這也是當你在開發者中心編輯了應用的授權,對應的配置文件會被標記為無效的原因。

如果你打開的是一個用於開發測試的證書,你會看到一項 ProvisionedDevices,在這一項裡包含了所有可以用於測試的設備列表。因為配置文件需要被蘋果簽名,所以每次你添加了新的設備進去就要重新下載新的配置文件。

總結

代碼簽名和配置文件這一套大概是一個 iOS 開發者必須處理的僅次於編碼的最復雜的問題之一。

雖然了解每一個部分是怎麼運作的很有幫助,但是要控制好所有這些設置和工具其實是一件很消耗時間的事情,特別是在一個開發團隊中,到處發送證書和配置文件顯然很不方便。雖然蘋果在最近幾次發布的 Xcode 中都嘗試改善,但是我不是很確定每一項改動都起到了好的作用。處理代碼簽名是每個開發者必過的大坑。

雖然處理代碼簽名對於開發者來說非常繁瑣,但不可否認正是它使得 iOS 對於用戶來說是一個非常安全的操作系統。所以為代碼簽名和配置文件進行的這些麻煩設置並不是徒勞無功。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved