iOS keyChain 研究

http://blog.csdn.net/jerryvon/article/details/16843065

一.基本知識
1.方法
SecItemAdd 增
SecItemUpdate 改
SecItemDelete 刪
SecItemCopyMatching 查

2.權限
文檔上說iOS的keyChain是一個相對獨立的空間准夷,當程序替換,刪除時并不會刪除keyChain的內(nèi)容,這個要比Library/Cache好拂苹。刷機,恢復出廠應該就沒有了。關于備份,只會備份數(shù)據(jù)旧找,到那時不會備份設備的密鑰,換句話說麦牺,即使拿到數(shù)據(jù)钮蛛,也沒有辦法解密里面的內(nèi)容鞭缭。有人說似乎破解的手機就能破解keyChain,本人并不清楚,希望有大神能指教魏颓。但個人認為岭辣,keyChain只是沙盒的升級版,可以存放一些非私密的信息甸饱,即使破解也不影響其它用戶沦童,只影響那個破解了的設備。(比如針對該設備的一個密鑰)柜候。

可訪問性一般來說搞动,自己的程序只能訪問自己的keychain,相同bundle的程序通過設置group可以互相共享同組的keychain躏精,從而實現(xiàn)程序間可以共同訪問一些數(shù)據(jù)渣刷。詳細后面介紹一些我測試下來的經(jīng)驗。

3.如何查詢keyChain

[objc] view plain copy

print?
genericPasswordQuery = [[NSMutableDictionary alloc] init];
[genericPasswordQuery setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];//1
[genericPasswordQuery setObject:identifier forKey:(id)kSecAttrGeneric];//2
******if** (accessGroup !=** nil){
[genericPasswordQuery setObject:accessGroup forKey:(
id)kSecAttrAccessGroup];//3
}
[genericPasswordQuery setObject:(
id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];//4
[genericPasswordQuery setObject:(
id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];//5
******NSDictionary
tempQuery = [NSDictionary dictionaryWithDictionary:genericPasswordQuery];
******NSMutableDictionary
* outDictionary =* nil;
******if
(SecItemCopyMatching((CFDictionaryRef)tempQuery, (CFTypeRef )&outDictionary) == noErr){//6
//found and outDicitionary is not nil
}
else*{
//not found
}

1.設置Class值矗烛,每個Class對應的都有不同的參數(shù)類型

2.用戶確定的參數(shù)辅柴,一般是程序中使用的類別,比如說是"Password"或"Account Info"瞭吃,作為search的主力條件
3.設置Group,如果不同程序都擁有這個組碌嘀,那么不同程序間可以共享這個組的數(shù)據(jù)
4.只返回第一個匹配數(shù)據(jù),查詢方法使用歪架,還有值kSecMatchLimitAll
5.返回數(shù)據(jù)為CFDicitionaryRef股冗,查詢方法使用
6.執(zhí)行查詢方法,判斷返回值
eg:這個是none-ARC的代碼哦和蚪!ARC情況下會有bridge提示止状。

4.類型轉換
介紹增刪改方法調用前,先介紹轉換方法攒霹,如何將NSDictionary轉換成KeyChain方法可以設置的Dicitionary怯疤,一般在寫程序過程中,應該盡量避免直接訪問KeyChain催束,一般會創(chuàng)建一個NSDictionary來同步對應的數(shù)據(jù)集峦,所以兩者需要做轉換。

[objc] view plain copy

print?
//data to secItem

  • (NSMutableDictionary )dictionaryToSecItemFormat:(NSDictionary* *)dictionaryToConvert
    {
    // Create a dictionary to return populated with the attributes and data.
    NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];

    //設置kSecClass
    [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    //將Dictionary里的kSecValueData(一般就是這個keyChain里主要內(nèi)容抠刺,比如說是password),NSString轉換成NSData
    NSString passwordString = [dictionaryToConvert objectForKey:(id)kSecValueData];
    [returnDictionary setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding] forKey:(
    id*)kSecValueData];
    return returnDictionary;
    }
    //secItem to data

  • (NSMutableDictionary )secItemFormatToDictionary:(NSDictionary* *)dictionaryToConvert
    {
    NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];

    // Add the proper search key and class attribute.
    [returnDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];

    // Acquire the password data from the attributes.
    NSData passwordData = NULL;
    if (SecItemCopyMatching((CFDictionaryRef)returnDictionary, (
    CFTypeRef* )&passwordData) == noErr)
    {
    // 刪除多余的kSecReturnData數(shù)據(jù)
    [returnDictionary removeObjectForKey:(
    id*)kSecReturnData];

      // 對應前面的步驟塔淤,將數(shù)據(jù)從NSData轉成NSString  
      **NSString** *password = [[[NSString alloc] initWithBytes:[passwordData bytes] length:[passwordData length]  
                                                   encoding:NSUTF8StringEncoding] autorelease];  
      [returnDictionary setObject:password forKey:(**id**)kSecValueData];  
    

    }
    else
    {
    NSAssert(NO, @"Serious error, no matching item found in the keychain.\n");
    }
    [passwordData release];
    return returnDictionary;
    }

5.增刪改
用代碼來說明

[objc] view plain copy

print?

  • (void)writeToKeychain
    {
    NSDictionary attributes = NULL;
    NSMutableDictionary updateItem = NULL;
    OSStatus result;
    //判斷是增還是改
    if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (
    CFTypeRef** )&attributes) == noErr)
    {
    // First we need the attributes from the Keychain.
    updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes];
    // Second we need to add the appropriate search key/values.
    [updateItem setObject:[genericPasswordQuery objectForKey:(
    id)kSecClass] forKey:(id)kSecClass];
    // Lastly, we need to set up the updated attribute list being careful to remove the class.
    NSMutableDictionary tempCheck = [
    self** dictionaryToSecItemFormat:keychainItemData];
    //刪除kSecClass update不能update該字段,否則會報錯
    [tempCheck removeObjectForKey:(id)kSecClass];
    //參數(shù)1表示search的速妖,參數(shù)2表示需要更新后的值
    result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);
    }else{
    //增加
    result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainItemData], NULL);
    }
    }

刪除很簡單凯沪,就不寫注釋了
[objc] view plain copy

print?

  • (void)resetKeychainItem
    {
    OSStatus junk = noErr;
    if (!keychainItemData)
    {
    self.keychainItemData = [[NSMutableDictionary alloc] init];
    }
    else if (keychainItemData)
    {
    NSMutableDictionary tempDictionary = [self* dictionaryToSecItemFormat:keychainItemData];
    junk = SecItemDelete((CFDictionaryRef)tempDictionary);
    NSAssert( junk == noErr || junk == errSecItemNotFound, @"Problem deleting current dictionary." );
    }

    // Default attributes for keychain item.
    [keychainItemData setObject:@"" forKey:(id)kSecAttrAccount];
    [keychainItemData setObject:@"" forKey:(id)kSecAttrLabel];
    [keychainItemData setObject:@"" forKey:(id)kSecAttrDescription];

    // Default data for keychain item.
    [keychainItemData setObject:@"" forKey:(id)kSecValueData];
    }

二.Group的配置
配置Target的Code Signing Entitlements.

配置該文件

可以配置一個Array列表,表示該程序可以支持多個group
這樣就可以在創(chuàng)建secItem時候添加kSecAttrAccessGroup了买优。
經(jīng)過測試有以下經(jīng)驗同大家分享:
1.相同bundle下生成的程序都可以共享相同group的keyChain.
相同bundle解釋下就是:比如:2個程序分別使用的provision對應bundle是com.jv.key1和com.jv.key2妨马,那你配置文件肯定是{Identifer}.com.jv.{name},其中identifer是蘋果生成的隨機串號挺举,可以在申請證書時看到,復制過來即可烘跺,name可以自己取湘纵,程序中指定屬于哪個Group即可。
2.如果你在 addkey時滤淳,沒有指定group,則會默認添加你keychain-access-groups里第一個group梧喷,如果你沒有設置Entitlements,則默認使用對應的程序的bundle name,比如com.jv.key1,表示只能給自己程序使用。
3.如果你程序添加的group并不存在你的配置文件中脖咐,程序會奔潰铺敌,表示無法添加。因此你只能添加你配置文件中支持的keychain屁擅。

參考資料:
蘋果文檔:
Keychain Services Reference

Certificate, Key, and Trust Services Programming Guide
Keychain Services Programming Guide

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末偿凭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子派歌,更是在濱河造成了極大的恐慌弯囊,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胶果,死亡現(xiàn)場離奇詭異匾嘱,居然都是意外死亡,警方通過查閱死者的電腦和手機早抠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門霎烙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蕊连,你說我怎么就攤上這事悬垃。” “怎么了咪奖?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵盗忱,是天一觀的道長。 經(jīng)常有香客問我羊赵,道長趟佃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任昧捷,我火速辦了婚禮闲昭,結果婚禮上,老公的妹妹穿的比我還像新娘靡挥。我一直安慰自己序矩,他們只是感情好,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布跋破。 她就那樣靜靜地躺著簸淀,像睡著了一般瓶蝴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上租幕,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天舷手,我揣著相機與錄音,去河邊找鬼劲绪。 笑死男窟,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的贾富。 我是一名探鬼主播歉眷,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼颤枪!你這毒婦竟也來了汗捡?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤汇鞭,失蹤者是張志新(化名)和其女友劉穎凉唐,沒想到半個月后庸追,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霍骄,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年淡溯,在試婚紗的時候發(fā)現(xiàn)自己被綠了读整。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡咱娶,死狀恐怖米间,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情膘侮,我是刑警寧澤屈糊,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站琼了,受9級特大地震影響逻锐,放射性物質發(fā)生泄漏。R本人自食惡果不足惜雕薪,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一昧诱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧所袁,春花似錦盏档、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懦窘。三九已至,卻和暖如春稚配,著一層夾襖步出監(jiān)牢的瞬間奶赠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工药有, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留毅戈,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓愤惰,卻偏偏與公主長得像苇经,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宦言,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容