1. 程式人生 > >iOS Keychain(鑰匙串)原理及使用

iOS Keychain(鑰匙串)原理及使用

iOS Keychain鑰匙串原理及使用

Keychain介紹

Keychain Services 是 macOS 和 iOS 都提供一種安全的儲存敏感資訊的工具,比如,網路密碼:使用者訪問伺服器或者網站,通用密碼:用來儲存應用程式或者資料庫密碼.與此同時,用於認證的證書,金鑰,和身份資訊,也可以儲存在Keychain中,Keychain Services 的安全機制保證了儲存這些敏感資訊不會被竊取。簡單說來,Keychain 就是一個安全容器。

在iOS中keychian 依賴用於簽名的provisioning profile描述檔案,確保釋出不同版本的時候使用同一個pp檔案

Keychain的結構

結構

如上圖,每一個keyChain的組成如圖,整體是一個字典結構.

  1. kSecClass key 定義屬於那一種型別的keyChain(通用密碼、網際網路密碼、證書、金鑰和身份)
  2. 不同的型別包含不同的Attributes,這些attributes定義了這個item的具體資訊
  3. 每個item可以包含一個密碼項來儲存對應的密碼

Keychain可以包含任意數量的keychain item(keychain item稱為SecItem,但它是儲存在CFDictionary中的).每一個keychain item包含資料和一組屬性。SecItem有五類:通用密碼、網際網路密碼、證書、金鑰和身份。在大多數情況下,我們用到的都是通用密碼

在macOS中,當keychain被鎖的時候加密的item沒辦法訪問,如果你想要該問被鎖的item,就會彈出一個對話方塊,需要你輸入對應keychain的密碼。當然,未有密碼的keychain你可以隨時訪問。但在iOS中,你只可以訪問你自已的keychain items

Keychain的特點

  • 資料並不存放在App的Sanbox中,即使刪除了App,資料依然儲存在keychain中。如果重新安裝了app,還可以從keychain獲取資料。

  • keychain的資料可以用過group方式,讓程式可以在App間共享。不過得要相同TeamID

  • keychain的資料是經過加密的

Keychain的使用

Apple針對keychain也提供了豐富的開發文件說明,包括有Keychain Services Programming Guide:文章中包含了使用mac和ios的keychain開發,首先介紹的是keychain的基本功能和概念,然後還有一個基本的例子介紹了基本的使用keychain API的方法

對於每一個應用來說,KeyChain都有兩個訪問區,私有區和公共區。私有區是一個sandbox,本程式儲存的任何資料都對其他程式不可見,其他應用程式無法訪問該區資料。如果要想將儲存的內容放在公共區,實現多個應用程式間可以共同訪問一些資料,則可以先宣告公共區的名稱,官方文件管這個名稱叫“keychain access group”

這裡我們先介紹 KeyChain 私有區的訪問儲存,即該私有區只能給自己程式使用。比如儲存使用者密碼,裝置唯一碼(UDID)等等

使用者密碼

大多數iOS應用需要用到Keychain, 都用來新增一個密碼,修改一個已存在Keychain item或者取回密碼。Keychain提供了以下的操作

  1. SecItemAdd 新增一個item

  2. SecItemUpdate 更新已存在的item

  3. SecItemCopyMatching 搜尋一個已存在的item

  4. SecItemDelete 刪除一個keychain item

當然對於只需要儲存使用者名稱和密碼的應用來說,SSKeyChain可能更加適合,它對keychain做了相應的封裝,介面相對來說更加簡單
通過以下類方法來使用SSKeyChain(請檢視SSKeyChain.h

+ (NSArray *)allAccounts;
+ (NSArray *)accountsForService:(NSString *)serviceName;
+ (NSString *)passwordForService:(NSString *)serviceNameaccount:(NSString *)account;
+ (BOOL)deletePasswordForService:(NSString *)serviceNameaccount:(NSString *)account;
+ (BOOL)setPassword:(NSString *)password forService:(NSString*)serviceName account:(NSString *)account;

SSKeyChain的方法中涉及到的變數主要有三個,分別是password、service、account。password、account分別儲存的是密碼和使用者名稱資訊。service儲存的是服務的型別,就是使用者名稱和密碼是為什麼應用儲存的一個標誌。比如一個使用者可以在不同的論壇中使用相同的使用者名稱和密碼,那麼service儲存的資訊分別標識不同的論壇。由於包名通常具有一定的唯一性,通常在程式中可以用包的名稱來作為service的標識

iOS 應用間共享 Keychain 資料

在 iOS 3.0 之後,應用間共享 keychain 資料成為了一種可能。但這是被嚴格限制的,只有擁有相同 App ID 字首的應用才有可能共享 keychai,並且各應用儲存的 keychain item 都標記了相同的 kSecAccessGroup 欄位值

  • 相同的Team ID
    有相同的 Team ID這個是應用間共享 Keychain 資料的前提條件。一個 App ID 分兩部分:

    1. Apple 為你生成的 Team ID
    2. 開發者註冊的 Bundle ID

    一個典型的 App ID 如:GPZ8FX842Q.com.apple.app, GPZ8FX842Q即為你的Team ID,是 Apple 為你生成的

一個開發者賬號可以有不同的幾個 Team ID。但 Apple 不會為不同的開發者生成一樣的 Team ID。這樣,不同的開發者賬號釋出的應用想共享 keychain 資料,在現在來看是無法實現的。而要做到 Keychain 資料共享,要求是同一個開發賬號開發的,同時選擇了相同的 Team ID

  • 開啟Keychain Sharing許可權
    Keychain Sharing開關

如圖開啟Keychain Sharing開關,設定好正確的 Keychain Group,設定好後應該會生成一個檔案,如下圖
在這裡插入圖片描述

並且會在 Project->build setting->Code Signing Entitlements 裡自動配置這個檔案的路徑
在這裡插入圖片描述

配置好後,須用你正式的證書籤名編譯才可通過。否則xcode會彈框告訴你code signing有問題。所以,蘋果限制了你只能同公司的產品共享KeyChain資料,別的公司訪問不了你公司產品的KeyChain