iOS的密碼管理系統(tǒng) Keychain的介紹和使用

Keychain 的介紹

Keychain 是蘋果公司 Mac OS(也包含 Mac OSX) 中的密碼管理系統(tǒng)最冰。

Keychain的作用

Keychain 可以包含許多種類型的數(shù)據(jù):密碼(包括網(wǎng)站鸿吆、FTP服務器柑肴、SSH賬戶、網(wǎng)絡共享证薇、無線網(wǎng)絡悠轩、群組軟件、加密磁盤鏡像)俊戳,私鑰,電子證書馆匿、加密筆記等抑胎。

Keychain 的四個方法介紹

1、存儲數(shù)據(jù)的方法

OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)

@attributes : 是要添加的數(shù)據(jù)渐北。
@result : 這是存儲數(shù)據(jù)后阿逃,返回一個指向該數(shù)據(jù)的引用,如果不是使用該引用時可以傳入 NULL 。

2恃锉、根據(jù)條件查詢數(shù)據(jù)

OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)

@query : 要查詢數(shù)據(jù)的條件搀菩。
@result: 根據(jù)條件查詢得到數(shù)據(jù)的引用。

3破托、更新數(shù)據(jù)

OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);

@query : 要更新數(shù)據(jù)的查詢條件肪跋。
@attributesToUpdate : 要更新的數(shù)據(jù)。

4土砂、刪除數(shù)據(jù)

OSStatus SecItemDelete(CFDictionaryRef query)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);

@query : 刪除的數(shù)據(jù)的查詢條件州既。

5、總結(jié)

以上四個方法萝映,就是Keychain 的常用的四個方法易桃,也就是 增、刪锌俱、改、查 敌呈。一般應用這四個方法就可以完全滿足贸宏。

Keychain 的一些Key 和 Value 的解釋和介紹

1、設置信息的保密程度

這里寫圖片描述

2磕洪、kSecClass 的可選value

這里寫圖片描述

3吭练、kSecClassGenericPassword 密碼所包含的所有類型參數(shù)

這里寫圖片描述

其他密碼的參數(shù)和普通密碼的參數(shù)大致相同,就不一一列舉析显。

Keychain 的封裝類KeyChainManager 的介紹和使用

1鲫咽、該類的 .h 文件

//
//  KeyChainManager.h
//  KeyChain
//
//  Created by MAC on 2017/11/8.
//  Copyright ? 2017年 NetworkCode小賤. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface KeyChainManager : NSObject

/*!
 保存數(shù)據(jù)

 @data  要存儲的數(shù)據(jù)
 @identifier 存儲數(shù)據(jù)的標示
 */
+(BOOL) keyChainSaveData:(id)data withIdentifier:(NSString*)identifier ;

/*!
 讀取數(shù)據(jù)

 @identifier 存儲數(shù)據(jù)的標示
 */
+(id) keyChainReadData:(NSString*)identifier ;


/*!
 更新數(shù)據(jù)

 @data  要更新的數(shù)據(jù)
 @identifier 數(shù)據(jù)存儲時的標示
 */
+(BOOL)keyChainUpdata:(id)data withIdentifier:(NSString*)identifier ;

/*!
 刪除數(shù)據(jù)

 @identifier 數(shù)據(jù)存儲時的標示
 */
+(void) keyChainDelete:(NSString*)identifier ;

@end

2、該類的 .m 文件

//
//  KeyChainManager.m
//  KeyChain
//  Created by MAC on 2017/11/8.
//  Copyright ? 2017年 NetworkCode小賤. All rights reserved.
//

#import "KeyChainManager.h"
#import <Security/Security.h>


@implementation KeyChainManager
/*!
 創(chuàng)建生成保存數(shù)據(jù)查詢條件
 */
+(NSMutableDictionary*) keyChainIdentifier:(NSString*)identifier {
    NSMutableDictionary * keyChainMutableDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword,kSecClass,identifier,kSecAttrService,identifier,kSecAttrAccount,kSecAttrAccessibleAfterFirstUnlock,kSecAttrAccessible, nil];
    return keyChainMutableDictionary;
}

/*!
 保存數(shù)據(jù)
 */
+(BOOL) keyChainSaveData:(id)data withIdentifier:(NSString*)identifier{
    // 獲取存儲的數(shù)據(jù)的條件
    NSMutableDictionary * saveQueryMutableDictionary = [self keyChainIdentifier:identifier];
    // 刪除舊的數(shù)據(jù)
    SecItemDelete((CFDictionaryRef)saveQueryMutableDictionary);
    // 設置新的數(shù)據(jù)
    [saveQueryMutableDictionary setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    // 添加數(shù)據(jù)
   OSStatus saveState = SecItemAdd((CFDictionaryRef)saveQueryMutableDictionary, nil);
    // 釋放對象
    saveQueryMutableDictionary = nil ;
    // 判斷是否存儲成功
    if (saveState == errSecSuccess) {
        return YES;
    }
    return NO;
}


/*!
 讀取數(shù)據(jù)
 */
+(id) keyChainReadData:(NSString*)identifier{
    id idObject = nil ;
    // 通過標記獲取數(shù)據(jù)查詢條件
    NSMutableDictionary * keyChainReadQueryMutableDictionary = [self keyChainIdentifier:identifier];
    // 這是獲取數(shù)據(jù)的時谷异,必須提供的兩個屬性
    // TODO: 查詢結(jié)果返回到 kSecValueData
    [keyChainReadQueryMutableDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    // TODO: 只返回搜索到的第一條數(shù)據(jù)
    [keyChainReadQueryMutableDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    // 創(chuàng)建一個數(shù)據(jù)對象
    CFDataRef keyChainData = nil ;
    // 通過條件查詢數(shù)據(jù)
    if (SecItemCopyMatching((CFDictionaryRef)keyChainReadQueryMutableDictionary , (CFTypeRef *)&keyChainData) == noErr){
        @try {
            idObject = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)(keyChainData)];
        } @catch (NSException * exception){
            NSLog(@"Unarchive of search data where %@ failed of %@ ",identifier,exception);
        }
    }
    if (keyChainData) {
        CFRelease(keyChainData);
    }
    // 釋放對象
    keyChainReadQueryMutableDictionary = nil;
    // 返回數(shù)據(jù)
    return idObject ;
}


/*!
 更新數(shù)據(jù)

 @data  要更新的數(shù)據(jù)
 @identifier 數(shù)據(jù)存儲時的標示
 */
+(BOOL)keyChainUpdata:(id)data withIdentifier:(NSString*)identifier {
    // 通過標記獲取數(shù)據(jù)更新的條件
    NSMutableDictionary * keyChainUpdataQueryMutableDictionary = [self keyChainIdentifier:identifier];
    // 創(chuàng)建更新數(shù)據(jù)字典
    NSMutableDictionary * updataMutableDictionary = [NSMutableDictionary dictionaryWithCapacity:0];
    // 存儲數(shù)據(jù)
    [updataMutableDictionary setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    // 獲取存儲的狀態(tài)
    OSStatus  updataStatus = SecItemUpdate((CFDictionaryRef)keyChainUpdataQueryMutableDictionary, (CFDictionaryRef)updataMutableDictionary);
    // 釋放對象
    keyChainUpdataQueryMutableDictionary = nil;
    updataMutableDictionary = nil;
    // 判斷是否更新成功
    if (updataStatus == errSecSuccess) {
        return  YES ;
    }
    return NO;
}


/*!
 刪除數(shù)據(jù)
 */
+(void) keyChainDelete:(NSString*)identifier {
    // 獲取刪除數(shù)據(jù)的查詢條件
    NSMutableDictionary * keyChainDeleteQueryMutableDictionary = [self keyChainIdentifier:identifier];
    // 刪除指定條件的數(shù)據(jù)
    SecItemDelete((CFDictionaryRef)keyChainDeleteQueryMutableDictionary);
    // 釋放內(nèi)存
    keyChainDeleteQueryMutableDictionary = nil ;
}

@end

KeyChainManager 類的測試使用

1分尸、測試代碼

// 存儲數(shù)據(jù)
BOOL save = [KeyChainManager keyChainSaveData:@"思念訴說,眼神多像云朵" withIdentifier:Keychain];
if (save) {
    NSLog(@"存儲成功");
}else {
    NSLog(@"存儲失敗");
}
// 獲取數(shù)據(jù)
NSString * readString = [KeyChainManager keyChainReadData:Keychain];
NSLog(@"獲取得到的數(shù)據(jù):%@",readString);

// 更新數(shù)據(jù)
BOOL updata = [KeyChainManager keyChainUpdata:@"長發(fā)落寞歹嘹,我期待的女孩" withIdentifier:Keychain];
if (updata) {
    NSLog(@"更新成功");
}else{
    NSLog(@"更新失敗");
}
// 讀取數(shù)據(jù)
NSString * readUpdataString = [KeyChainManager keyChainReadData:Keychain];
NSLog(@"獲取更新后得到的數(shù)據(jù):%@",readUpdataString);

// 刪除數(shù)據(jù)
[KeyChainManager keyChainDelete:Keychain];
// 讀取數(shù)據(jù)
NSString * readDeleteString = [KeyChainManager keyChainReadData:Keychain];
NSLog(@"獲取刪除后得到的數(shù)據(jù):%@",readDeleteString);

2箩绍、測試結(jié)果的展示

這里寫圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市尺上,隨后出現(xiàn)的幾起案子材蛛,更是在濱河造成了極大的恐慌,老刑警劉巖怎抛,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卑吭,死亡現(xiàn)場離奇詭異,居然都是意外死亡马绝,警方通過查閱死者的電腦和手機豆赏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人河绽,你說我怎么就攤上這事己单。” “怎么了耙饰?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵纹笼,是天一觀的道長。 經(jīng)常有香客問我苟跪,道長廷痘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任件已,我火速辦了婚禮笋额,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘篷扩。我一直安慰自己兄猩,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布鉴未。 她就那樣靜靜地躺著枢冤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪铜秆。 梳的紋絲不亂的頭發(fā)上淹真,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音连茧,去河邊找鬼核蘸。 笑死,一個胖子當著我的面吹牛啸驯,可吹牛的內(nèi)容都是我干的客扎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼坯汤,長吁一口氣:“原來是場噩夢啊……” “哼虐唠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起惰聂,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤疆偿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后搓幌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體杆故,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年溉愁,在試婚紗的時候發(fā)現(xiàn)自己被綠了处铛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饲趋。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖撤蟆,靈堂內(nèi)的尸體忽然破棺而出奕塑,到底是詐尸還是另有隱情,我是刑警寧澤家肯,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布龄砰,位于F島的核電站,受9級特大地震影響讨衣,放射性物質(zhì)發(fā)生泄漏换棚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一反镇、第九天 我趴在偏房一處隱蔽的房頂上張望固蚤。 院中可真熱鬧,春花似錦歹茶、人聲如沸夕玩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽风秤。三九已至,卻和暖如春扮叨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背领迈。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工彻磁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人狸捅。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓衷蜓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尘喝。 傳聞我的和親對象是個殘疾皇子磁浇,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

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